Spring-Cloud Euraka 是 Spring Cloud 汇合中一个组件,它是对 Euraka 的集成,用于服务注册和发现。Eureka 是 Netflix 中的一个开源框架。它和 zookeeper、Consul 一样,都是用于服务注册治理的,同样,Spring-Cloud 还集成了 Zookeeper 和 Consul。
搭建 eureka 服务注册核心
引入以下依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- 最新版的 eureka 服务端包 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
<!-- SpringCloud 依赖,起到治理版本的作用 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR9</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Spring Cloud 和 Spring Boot 之间版本对应关系
Release Train | Boot Version |
---|---|
2020.0.x aka Ilford | 2.4.x |
Hoxton | 2.2.x, 2.3.x (Starting with SR5) |
Greenwich | 2.1.x |
Finchley | 2.0.x |
Edgware | 1.5.x |
Dalston | 1.5.x |
在启动类上增加 @EnableEurekaServer
注解,表明这是一个 Eureka 服务端
@SpringBootApplication
@EnableEurekaServer
public class SpringCloudEurekaApplication {public static void main(String[] args) {SpringApplication.run(SpringCloudEurekaApplication.class, args);
}
}
在 application.properties 中增加一些配置
server.port=8080
spring.application.name=Eureka-Server
# 指定了 Eureka 服务端的 IP
eureka.instance.hostname=localhost
eureka.instance.statusPageUrl=http://${eureka.instance.hostname}:${server.port}/info
eureka.instance.healthCheckUrl=http://${eureka.instance.hostname}:${server.port}/health
eureka.instance.homePageUrl=http://${eureka.instance.hostname}/
# 示意是否将服务注册到 Eureka 服务端,因为本身就是 Eureka 服务端,所以设置为 false
# eureka.client.register-with-eureka=false
# 示意是否从 Eureka 服务端获取服务信息,因为这里只搭建了一个 Eureka 服务端,并不需要从别的 Eureka 服务端同步服务信息,所以这里设置为 false
# eureka.client.fetch-registry=false
# 指定 Eureka 服务端的地址,默认值为 http://localhost:8761/eureka 指定 Eureka 服务端的地址为另外一个 Eureka 服务端的地址 8081
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/
# 用于定义服务续约工作的调用间隔时间,默认 30 秒
eureka.client.serviceUrl.registry-fetch-interval-seconds=5
配置结束后启动服务,拜访 http://localhost:8080/
因为还没有 Eureka 客户端将服务注册进来,所以 Instances currently registered with Eureka 列表是空的
搭建 provider 服务提供者
引入以下依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</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-web</artifactId>
</dependency>
<!-- 监控治理 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
<!-- SpringCloud 依赖,起到治理版本的作用 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR9</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
在启动类上加 @EnableDiscoveryClient
注解,表明这是一个 Eureka 客户端
@SpringBootApplication
@EnableDiscoveryClient
public class SpringCloudProviderApplication {public static void main(String[] args) {SpringApplication.run(SpringCloudProviderApplication.class, args);
}
}
接着编写一个 TestController,对外提供一些 REST 服务
@RestController
public class TestController {@GetMapping("/hello")
public String hello() {return "hello world";}
}
在 application.properties 中增加一些配置
# 指定了服务的端口为 8081
server.port=8082
# 指定服务名称为 Server-Provider,后续服务消费者要获取下面 TestController 中接口的时候会用到这个服务名
spring.application.name=Server-Provider
# 尽管这两个配置的默认值就是 true,但这里还是显式配置下,使 Eureka 客户端的性能更为直观(即向服务端注册服务并定时从服务端获取服务缓存到本地)eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true
# 指定 Eureka 服务端的地址,这里为下面定义的 Eureka 服务端地址
eureka.client.serviceUrl.defaultZone=http://localhost:8080/eureka/,http://localhost:8081/eureka/
# 拜访门路能够显示 IP 地址
eureka.instance.prefer-ip-address=true
配置好后,启动 Eureka-Client,能够从控制台中看到注册胜利的音讯
Registered Applications size is zero : true
Application version is -1: true
Getting all instance registry info from the eureka server
The response status is 200
Starting heartbeat executor: renew interval is: 30
InstanceInfoReplicator onDemand update allowed rate per min is 4
Discovery Client initialized at timestamp 1611244216061 with initial instances count: 0
Registering application SERVER-PROVIDER with eureka with status UP
Saw local status change event StatusChangeEvent [timestamp=1611244216076, current=UP, previous=STARTING]
DiscoveryClient_SERVER-PROVIDER/DESKTOP-7LUOFJF.lan:Server-Provider:8081: registering service...
Tomcat started on port(s): 8081 (http) with context path ''
Updating port to 8081
DiscoveryClient_SERVER-PROVIDER/DESKTOP-7LUOFJF.lan:Server-Provider:8081 - registration status: 204
再次拜访 http://localhost:8082/,可看到服务列表里曾经呈现了名字为 Server-providerde 服务了
UP 示意在线的意思(如果 Eureka 客户端失常敞开,那么这里的状态将变为 DOWN),点击前面的链接 http://192.168.68.233:8081/actuator/info 将拜访该服务的 /info
接口:
{"app":{"name":"Server-Provider"}}
这时候敞开 Eureka 客户端,再次刷新 http://localhost:8080/
可看到尽管 Eureka 客户端曾经敞开了,然而 Eureka 服务端页面的服务服务列表中仍然还有该服务,并且页面红色文字提醒
EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY’RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.
大抵意思是 Eureka 曾经进入了 保护模式。微服务在部署之后可能因为网络问题造成 Eureka 客户端无奈胜利的发送心跳给 Eureka 服务端,这时候 Eureka 服务端认定 Eureka 客户端曾经挂掉了,尽管实际上 Eureka 客户端还在失常的运行着。而保护模式就是为了解决这个问题,即当 Eureka 服务端在短时间内同时失落了过多的 Eureka 客户端时,Eureka 服务端会进入保护模式,不去剔除这些客户端。因为咱们这里只部署了一个 Eureka 客户端服务,所以敞开客户端后满足“短时间内失落过多 Eureka 客户端”的条件。
在开发中能够先将保护模式给关了,咱们在 Eureka 服务端加上一条配置
eureka.server.enable-self-preservation= false
开启服务监控 actuator
引入以下依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
在 application.properties 中增加一些配置
# 启用监控
# 凋谢所有端点 health,info,metrics,通过 actuator/+ 端点名就能够获取相应的信息。默认关上 health 和 info,metrics 默认不凋谢
management.endpoints.web.exposure.include=*
#未开启 actuator/health 时,咱们获取到的信息是{"status":"UP"},status 的值还有可能是 DOWN。开启后打印详细信息
management.endpoint.health.show-details=always
info.app.name=Server-Provider
拜访门路
localhost 依据本人部署的服务器 IP、主机名拜访。info、health 为默认凋谢,metrics 默认不凋谢
- 心跳查看 http://localhost:8081/actuator/info
- 健康检查 http://localhost:8081/actuator/health
- 指标 http://localhost:8081/actuator/metrics
Eureka 集群
ureka 服务端充当了重要的角色,所有 Eureka 客户端都将本人提供的服务注册到 Eureka 服务端,而后供所有服务消费者应用。如果单节点的 Eureka 服务端宕机了,那么所有服务都无奈失常的拜访,这必将是灾难性的。为了进步 Eureka 服务端的可用性,咱们个别会对其集群部署,即同时部署多个 Eureka 服务端,并且能够相互间同步服务。
在搭建 Eureka 服务端的时候咱们曾把上面两个配置给敞开了
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
实际上在 Eureka 集群模式中,开启这两个参数能够让以后 Eureka 服务端将本人也作为服务注册到别的 Eureka 服务端,并且从别的 Eureka 服务端获取服务进行同步。所以这里咱们将这两个参数置为 true(默认就是 true),上面开始搭建 Eureka 服务端集群,为了简略起见这里只搭建两个节点的 Eureka 服务端集群。
两个 applications.properties 配置如下
- 8080 端口的 Eureka 服务端
server.port=8080
spring.application.name=Eureka-Server
# 指定了 Eureka 服务端的 IP
eureka.instance.hostname=localhost
eureka.instance.statusPageUrl=http://${eureka.instance.hostname}:${server.port}/info
eureka.instance.healthCheckUrl=http://${eureka.instance.hostname}:${server.port}/health
eureka.instance.homePageUrl=http://${eureka.instance.hostname}/
# 示意是否将服务注册到 Eureka 服务端,因为本身就是 Eureka 服务端,所以设置为 false
# eureka.client.register-with-eureka=false
# 示意是否从 Eureka 服务端获取服务信息,因为这里只搭建了一个 Eureka 服务端,并不需要从别的 Eureka 服务端同步服务信息,所以这里设置为 false
# eureka.client.fetch-registry=false
# 指定 Eureka 服务端的地址,默认值为 http://localhost:8761/eureka 指定 Eureka 服务端的地址为另外一个 Eureka 服务端的地址 8081
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:8081/eureka/
# 用于定义服务续约工作的调用间隔时间,默认 30 秒
eureka.client.serviceUrl.registry-fetch-interval-seconds=5
# 敞开保护模式
eureka.server.enable-self-preservation=false
- 8081 端口的 Eureka 服务端
server.port=8081
spring.application.name=Eureka-Server
# 指定了 Eureka 服务端的 IP
eureka.instance.hostname=localhost
eureka.instance.statusPageUrl=http://${eureka.instance.hostname}:${server.port}/info
eureka.instance.healthCheckUrl=http://${eureka.instance.hostname}:${server.port}/health
eureka.instance.homePageUrl=http://${eureka.instance.hostname}/
# 示意是否将服务注册到 Eureka 服务端,因为本身就是 Eureka 服务端,所以设置为 false
# eureka.client.register-with-eureka=false
# 示意是否从 Eureka 服务端获取服务信息,因为这里只搭建了一个 Eureka 服务端,并不需要从别的 Eureka 服务端同步服务信息,所以这里设置为 false
# eureka.client.fetch-registry=false
# 指定 Eureka 服务端的地址,默认值为 http://localhost:8761/eureka 指定 Eureka 服务端的地址为另外一个 Eureka 服务端的地址 8080
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:8080/eureka/
# 用于定义服务续约工作的调用间隔时间,默认 30 秒
eureka.client.serviceUrl.registry-fetch-interval-seconds=5
# 敞开保护模式
eureka.server.enable-self-preservation=false
搭建 consumer 服务消费者
Eureka 客户端即是服务提供者,也是服务消费者,即本身的接口可能被别的服务拜访,同时也可能调用别的服务接口
引入一下依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</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-web</artifactId>
</dependency>
</dependencies>
<!-- SpringCloud 依赖,起到治理版本的作用 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR9</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
在入口类中退出 @EnableDiscoveryClient
注解用于发现服务和注册服务,并配置一个 RestTemplate Bean
,而后加上@LoadBalanced
注解来开启负载平衡
@SpringBootApplication
@EnableDiscoveryClient
public class SpringCloudConsumerApplication {
@Bean
@LoadBalanced
RestTemplate restTemplate() {return new RestTemplate();
}
public static void main(String[] args) {SpringApplication.run(SpringCloudConsumerApplication.class, args);
}
}
编写一个 TestController,用于生产服务
@RestController
public class TestController {
@Autowired
private RestTemplate restTemplate;
/**
* 注入了 RestTemplate,getInfo 中应用 RestTemplate 对象平衡的去获取服务并生产。* 能够看到咱们应用服务名称(Server-Provider)去获取服务的,而不是应用传统的 IP 加端口的模式。* 这就体现了应用 Eureka 去获取服务的益处,咱们只有保障这个服务名称不变即可,IP 和端口不再是咱们关怀的点
*
* @return
*/
@GetMapping("/info")
public String getInfo() {return this.restTemplate.getForEntity("http://Server-Provider/hello", String.class).getBody();}
}
在 application.properties 中增加一些配置
# 指定了服务的端口为 8083
server.port=8083
# 指定服务名称为 Server-Consumer,后续服务消费者要获取下面 TestController 中接口的时候会用到这个服务名
spring.application.name=Server-Consumer
# 尽管这两个配置的默认值就是 true,但这里还是显式配置下,使 Eureka 客户端的性能更为直观(即向服务端注册服务并定时从服务端获取服务缓存到本地)eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true
# 指定 Eureka 服务端的地址,这里为下面定义的 Eureka 服务端地址
eureka.client.serviceUrl.defaultZone=http://localhost:8080/eureka/,http://localhost:8081/eureka/
# 拜访门路能够显示 IP 地址
eureka.instance.prefer-ip-address=true
启动该我的项目,拜访 http://localhost:8083/info
Eureka 增加认证
出于平安的思考,咱们可能会对 Eureka 服务端增加用户认证的性能。咱们在 Eureka-Server 引入 Spring-Security 依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
而后在 application.yml 中配置用户名和明码
spring.security.user.name=admin
spring.security.user.password=123456
Eureka 服务端配置了明码之后,所有 eureka.client.serviceUrl.defaultZone
的配置也必须配置上用户名和明码,格局为:eureka.client.serviceUrl.defaultZone=http://${userName}:${password}@${hosetname}:${port}/eureka/
,如:
eureka.client.serviceUrl.defaultZone=http://admin:123456@${eureka.instance.hostname}:8080/eureka/
从新打包并部署后,拜访 http://localhost:8080/,页面将弹出验证窗口,输出用户名和明码后即可拜访
Eureka 配置
Eureka 中罕用的配置选项及代表的含意
配置 | 含意 | 默认值 |
---|---|---|
eureka.client.enabled | 是否启用 Eureka Client | true |
eureka.client.register-with-eureka | 示意是否将本人注册到 Eureka Server | true |
eureka.client.fetch-registry | 示意是否从 Eureka Server 获取注册的服务信息 | true |
eureka.client.serviceUrl.defaultZone | 配置 Eureka Server 地址,用于注册服务和获取服务 | http://localhost:8761/eureka |
eureka.client.registry-fetch-interval-seconds | 默认值为 30 秒,即每 30 秒去 Eureka Server 上获取服务并缓存 | 30 |
eureka.instance.lease-renewal-interval-in-seconds | 向 Eureka Server 发送心跳的间隔时间,单位为秒,用于服务续约 | 30 |
eureka.instance.lease-expiration-duration-in-seconds | 定义服务生效工夫,即 Eureka Server 检测到 Eureka Client 木有心跳后(客户端意外下线)多少秒将其剔除 | 90 |
eureka.server.enable-self-preservation | 用于开启 Eureka Server 自我爱护性能 | true |
eureka.client.instance-info-replication-interval-seconds | 更新实例信息的变动到 Eureka 服务端的间隔时间,单位为秒 | 30 |
eureka.client.eureka-service-url-poll-interval-seconds | 轮询 Eureka 服务端地址更改的间隔时间,单位为秒。 | 300 |
eureka.instance.prefer-ip-address | 示意应用 IP 进行配置为不是域名 | false |
eureka.client.healthcheck.enabled | 默认 Erueka Server 是通过心跳来检测 Eureka Client 的健康状况的,通过置为 true 扭转 Eeureka Server 对客户端衰弱检测的形式,改用 Actuator 的 /health 端点来检测。 | false |
Eureka 还有许多别的配置,具体能够参考 EurekaClientConfigBean
,EurekaServerConfigBean
和EurekaInstanceConfigBean
配置类的源码。
References
[1] Spring Cloud Netflix: https://cloud.spring.io/spring-cloud-netflix/reference/html/#service-discovery-eureka-clients