注册中心-Eureka

0
字数 2.3k
阅读时间 4 分钟

Eureka

Eureka 的 Github 项目 Wiki 对 Eureka 描述如下:

What is Eureka?

Eureka is a REST (Representational State Transfer) based service that is primarily used in the AWS cloud for locating services for the purpose of load balancing and failover of middle-tier servers. We call this service, the Eureka Server. Eureka also comes with a Java-based client component,the Eureka Client, which makes interactions with the service much easier. The client also has a built-in load balancer that does basic round-robin load balancing. At Netflix, a much more sophisticated load balancer wraps Eureka to provide weighted load balancing based on several factors like traffic, resource usage, error conditions etc to provide superior resiliency.

什么是 Eureka?

Eureka 是一种基于 REST(Representational State Transfer)的服务,主要用于 AWS 云,用于定位服务,以实现中间层服务器的负载平衡和故障转移。我们将此服务称为 Eureka Server。Eureka 还附带了一个基于 Java 的客户端组件 Eureka Client,它使与服务的交互变得更加容易。客户端还有一个内置的负载均衡器,可以进行基本的循环负载均衡。在 Netflix,一个更复杂的负载均衡器包含 Eureka 基于流量,资源使用,错误条件等多种因素提供加权负载平衡,以提供卓越的弹性。

简单来说官方对 Eureka 的定位是定位服务,负载均衡,故障转移

创建 Eureka 项目

创建 eureka 项目依赖继承 discovery-center 项目,pom.xml 内容为:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.github.liuzhuoming23</groupId>
<artifactId>discovery-center</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<packaging>jar</packaging>

<artifactId>eureka</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>eureka</name>
<description>Demo project for Spring Cloud</description>


<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>

在启动类 EurekaController 添加注解@EnableEurekaServer

package com.github.liuzhuoming23.eureka;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

/**
* 启动类
*
* @author liuzhuoming
*/
@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {

public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}

}

在 application.yml 添加配置:

server:
#服务端口
port: 8000

spring:
application:
#服务名称(使用项目名称)
name: @pom.artifactId@

eureka:
instance:
#服务实例hostname
hostname: localhost
client:
#是否注册到eureka(单节点设置false)
register-with-eureka: false
#是否获取注册信息(单节点设置false)
fetch-registry: false
service-url:
#注册服务地址
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

启动项目,访问http://localhost:8000,显示页面如下:
01.jpg
说明注册中心启动成功了。

注册中心集群

因为没有多服务器环境,而且貌似注册中心集群不支持多个 localhost 相互注册,所以请自行实验。

服务生产者

创建服务生产者

创建 producer-client 项目继承 server-center 项目,pom.xml 内容为:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.github.liuzhuoming23</groupId>
<artifactId>server-center</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<packaging>jar</packaging>

<artifactId>producer-client</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>producer-client</name>
<description>Demo project for Spring Cloud</description>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>

其中 spring-boot-starter-actuator 依赖作用是项目健康监控,加上这个依赖后可以在开启 endpoint 后获取项目的对应信息,其和 Spring Admin 和 Eureka 等都有很好的集成,感兴趣的可以单独去学习,在此只为辅助完成项目搭建,具体不作赘述。
在 controller 目录新建 PortController,内容为:

package com.github.liuzhuoming23.producerclient.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
* port
*
* @author liuzhuoming
*/
@RestController
@RequestMapping("port")
public class PortController {

@Value("${server.port:0}")
private Integer port;

@GetMapping("{name}")
public String port(@PathVariable String name) {
return name + ": client port | " + port;
}
}

application.yml 配置为:

server:
port: 8010

spring:
application:
name: @pom.artifactId@

eureka:
client:
service-url:
#服务注册地址
defaultZone: http://localhost:8000/eureka/

启动项目,再次访问http://localhost:8000,可以看到 producer-client 实例已经注册进去了:
02.jpg
访问http://localhost:8010/port/🐒,返回数据为:
🐒: client port | 8010

服务生产者集群

在 IntelliJ IDEA 的 Run/Debug Configurations 修改 ProducerClientApplication 启动类启动方式为并行启动(即可以开启多个实例):
03.jpg
然后修改 producer-client 项目的 application.yml 的端口为 8081:

server:
port: 8081

spring:
application:
name: @pom.artifactId@

eureka:
client:
service-url:
#服务注册地址
defaultZone: http://localhost:8000/eureka/

并再次启动,启动方式是在已经启动一个实例的情况下点击右上角的三角启动按钮(可以注意到启动按钮右下角多了一个小绿点表示已开启并行启动),之后可以在 Euraka 管理页面看到:
04.jpg
说明服务生产者集群注册成功(x-047 为计算机名称,localhost 为本机 ip(本 doom 只运行于本地))。
这里遇到个 bug 就是在项目依赖包含 devtool 的时候开启 IntelliJ IDEA 并行启动,在启动第二个并行实例的时候就会报错端口已被占用,所以请删除 devtool 依赖再启动第二个并行实例

注册中心开启 Spring Security 认证

注册中心配置修改

因为 Eureka 管理中心可以看到所有注册到注册中心的服务基本情况,所以需要添加认证防止被随意访问。
首先在 eureka 项目添加 spring-cloud-starter-security 依赖:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.github.liuzhuoming23</groupId>
<artifactId>discovery-center</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<packaging>jar</packaging>

<artifactId>eureka</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>eureka</name>
<description>Demo project for Spring Cloud</description>

<properties>
<java.version>8</java.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-security</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>

修改 application.yml 添加基本认证:

server:
port: 8000

spring:
application:
name: @pom.artifactId@
security:
user:
#基本认证账户名
name: 'admin'
#基本认证密码
password: 'admin'

eureka:
instance:
hostname: localhost
client:
register-with-eureka: false
fetch-registry: false
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

并在项目中添加 config.WebSecurityConfig 配置类,继承 WebSecurityConfigurerAdapter 类并重写 configure 方法(主要用于关闭默认开启的 csrf 校验,避免服务无法注册):

package com.github.liuzhuoming23.eureka.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

/**
* 安全认证配置
*
* @author liuzhuoming
*/
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin().and()
.httpBasic();
}
}

重新启动项目,并访问http://localhost:8000,可以看到基本认证已经添加了:
05.jpg
输入在 application.yml 配置的账号密码 admin:admin 就可以登录了,之后页面内容和未添加认证没区别,不再赘述。

服务生产者配置修改

在注册中心添加认证后,尝试启动服务生产者,会报错:

com.netflix.discovery.shared.transport.TransportException: Cannot execute request on any known server

需要在服务生产者的 application.yml 的注册中心地址添加账号密码认证:

server:
port: 8010

spring:
application:
name: @pom.artifactId@

eureka:
client:
service-url:
defaultZone: http://admin:admin@localhost:8000/eureka/

就可以成功注册到注册中心了。


系列文章 #Spring Cloud

(1)前言

(2)注册中心-Eureka

(3)服务间调用-Feign(🔒)

(4)路由中心-Gateway

(5)配置中心-Config

(6)配置中心-Bus

(7)监控中心-Admin

(8)监控中心-Sleuth+Zipkin(🔒)

(9)监控中心-Elasticsearch+Zipkin(🔒)

(10)监控中心-HystrixDashboard+Turbine(🔒)

(11)授权中心-Oauth2+JWT

(12)注册中心/配置中心-Nacos

(13)动态路由-Gateway

(14)授权中心-Oauth2+JWT补全


服务间调用-Feign 前言