SpringCloud Eureka做服务治理和 Eureka注册中心集群搭建 及 自我保护机制
SpringCloud Eureka做服务治理和 Eureka注册中心集群搭建 及 自我保护机制
一、注册中心
注册中心可以说是微服务架构中的”通讯录“,它记录了服务和服务地址的映射关系。在分布式架构中,服务会注册到这里,当服务需要调用其它服务时,就到这里找到服务的地址,进行调用。
举个现实生活中的例子,比如说,我们手机中的通讯录的两个使用场景:
当我想给张三打电话时,那我需要在通讯录中按照名字找到张三,然后就可以找到他的手机号拨打电话。李四办了手机号,那么他把手机号告诉我,我把李四的号码存进通讯录,后续,我就可以从通讯录找到他。
二、Eureka注册中心
Eureka是基于REST(Representational State Transfer)服务,主要以AWS云服务为支撑,提供服务发现并实现负载均衡和故障转移。我们称此服务为Eureka服务。Eureka提供了Java客户端组件,Eureka Client,方便与服务端的交互。客户端内置了基于round-robin实现的简单负载均衡。在Netflix,为Eureka提供更为复杂的负载均衡方案进行封装,以实现高可用,它包括基于流量、资源利用率以及请求返回状态的加权负载均衡。
三、搭建注册中心
本文是基于springboot 2.0.1,环境进行搭建的,不同版本springcloud集成方式略有不同,请注意下。
- 首先新建个springboot项目,该项目作为注册中心,导入pom依赖
<!--SpringCloud eureka-server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
- 1
- 2
- 3
- 4
- 5
下面的两个依赖不管是服务端还是客户端都需要添加,后面不再说明。
<!-- 管理依赖 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.M7</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
<!-- 注意: 这里必须要添加, 否者各种依赖有问题 -->
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/libs-milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 然后是application.properties
server.port= 8679
###eureka 基本信息配置
###注册到eurekaip地址
eureka.instance.hostname=127.0.0.1
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/
###因为自己是为注册中心,不需要自己注册自己
eureka.client.register-with-eureka=false
###因为自己是为注册中心,不需要检索服务
eureka.client.fetch-registry=false
# 关闭自我保护机制,保证不可用的服务被及时剔除 true为开启 false为关闭
eureka.server.enable-self-preservation= false
# 如果2秒内没有收到某个微服务的心跳,那就剔除该微服务,单位为毫秒
eureka.server.eviction-interval-timer-in-ms= 2000
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
上面的配置中指出了注册中心的端口和地址,这个需要记住,等下配置服务的发现和注册需要指向注册中心ip和端口。
- 启动Eureka服务
在启动类的上面添加注解:
@EnableEurekaServer
- 1
表明当前是Eureka的注册中心,然后启动项目,然后在浏览器输入localhost:8679,可以看下如下界面证明Eureka注册中心配置成功。
四、搭建服务提供者
- 新建一个springboot项目作为服务提供者,导入pom依赖
<!-- SpringBoot整合eureka客户端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
- 1
- 2
- 3
- 4
- 5
- 配置application.properties
server.port=8081
###服务名称(服务注册到eureka名称)
spring.application.name=eurekaprovice
###服务注册到eureka地址
eureka.client.service-url.defaultZone = http://localhost:8679/eureka
###注册自己
eureka.client.register-with-eureka=true
###是否需要从eureka上获取注册信息
eureka.client.fetch-registry=true
#心跳检测与续约时间(开发环境可以将值设小一点,保证服务关闭后注册中心能及时剔除)
eureka.instance.lease-expiration-duration-in-seconds=90
#Eureka客户端向服务端发送心跳的时间间隔,单位为秒(客户端告诉服务端自己会遵循该规则)
eureka.instance.lease-renewal-interval-in-seconds=30
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
其中指定了端口号,和指向注册中心的地址,其中spring.application.name为注册到注册中心的名称,如果有多个相同名称的项目一起注册到了注册中心去,eureka相当于为我们管理了一个集群,后面如果通过rest方式可通过注解开启负载均衡,用Feign调用服务会默认开启了负载均衡。
- 然后写一个Controller接口,作为服务。
@RestController
public class TestController {
@Value("${server.port}")
int port;
@GetMapping("/GetTest")
public String GetTest(){
return "服务提供者 port:= "+port;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
4.最后在启动类上面添加注解。
@EnableEurekaClient
- 1
然后启动该项目后,去刚才注册中心的网页上去查看状态
可以看到当前在Eureka注册的实例已经多了一个,而他的Application的名字就是,上面我们指定的spring.application.name的名字,只不过他都是大写的,加入我们再建一个项目,和该项目配置一样但想端口改为8082,配置如下:
server.port=8082
###服务名称(服务注册到eureka名称)
spring.application.name=eurekaprovice
###服务注册到eureka地址
eureka.client.service-url.defaultZone = http://localhost:8679/eureka
###注册自己
eureka.client.register-with-eureka=true
###是否需要从eureka上获取注册信息
eureka.client.fetch-registry=true
#心跳检测与续约时间(开发环境可以将值设小一点,保证服务关闭后注册中心能及时剔除)
eureka.instance.lease-expiration-duration-in-seconds=90
#Eureka客户端向服务端发送心跳的时间间隔,单位为秒(客户端告诉服务端自己会遵循该规则)
eureka.instance.lease-renewal-interval-in-seconds=30
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
可以看到除了端口不一样外,其他都一样,再运行该项目,再看注册中心的状态。
此时当前在Eureka注册的实例,可以看到UP(2),说明有两台相同的客户端注册了上来,此时相当于搭建了一个服务提供者集群,下面客户端使用rest连接的时候就可以看到负载均衡轮询效果。
五、服务消费者
- 同样新建一个springboot项目作为服务提供者,导入pom依赖
<!-- SpringBoot整合eureka客户端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
- 1
- 2
- 3
- 4
- 5
- 配置application.properties
server.port=8083
###服务名称(服务注册到eureka名称)
spring.application.name=eurekaconsumer
###服务注册到eureka地址
eureka.client.service-url.defaultZone = http://localhost:8679/eureka
###注册自己
eureka.client.register-with-eureka=true
###是否需要从eureka上获取注册信息
eureka.client.fetch-registry=true
#心跳检测与续约时间(开发环境可以将值设小一点,保证服务关闭后注册中心能及时剔除)
eureka.instance.lease-expiration-duration-in-seconds=90
#Eureka客户端向服务端发送心跳的时间间隔,单位为秒(客户端告诉服务端自己会遵循该规则)
eureka.instance.lease-renewal-interval-in-seconds=30
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
可以看出这里配置和服务提供者一样。
- 配置RestTemplate
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
- 1
- 2
- 3
- 4
- 5
其中@LoadBalanced代表着开启负载均衡。
- 消费服务
@RestController
public class TestController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/GetTest")
public String GetTest(){
String memberUrl = "http://eurekaprovice/GetTest";
String result = restTemplate.getForObject(memberUrl, String.class);
System.out.println("调用远程服务,result:" + result);
return result;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
其中memberUrl 指向的便是服务提供者的名称+接口名。
- 最后还要再启动类上面添加注解
@EnableEurekaClient
- 1
然后再浏览器访问 localhost:8083/GetTest,可以看到8081,和8082服务提供者被论训的访问,实现了负载均衡的效果。
六、Eureka集群的搭建
前面虽然已经搭建成功了rpc远程调用,但注册中心只有一个,一旦注册中心挂了,所有的服务将不可用,所以注册中心需要搭建成集群的形式,一台挂了不会影响其他的正常运行,而eureka搭建注册中心集群非常简单,只需要注册的地址指向其他节点即可。
假入现在有三台服务器端口为8091,8092,8093需要搭建Eureka注册中心节点,则配置文件为
server.port= 8091
###eureka 基本信息配置
###注册到eurekaip地址
eureka.instance.hostname=127.0.0.1
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:8092/eureka/,http://${eureka.instance.hostname}:8093/eureka/
###因为自己是为注册中心,不需要自己注册自己
eureka.client.register-with-eureka=false
###因为自己是为注册中心,不需要检索服务
eureka.client.fetch-registry=false
# 关闭自我保护机制,保证不可用的服务被及时剔除 true为开启 false为关闭
eureka.server.enable-self-preservation= false
# 如果2秒内没有收到某个微服务的心跳,那就剔除该微服务,单位为毫秒
eureka.server.eviction-interval-timer-in-ms= 2000
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
其他两个节点配置相同,只需将地址指向其他节点即可。
七、Eureka 自我保护
默认情况下,EurekaClient会定时向EurekaServer端发送心跳,如果EurekaServer在一定时间内没有收到EurekaClient发送的心跳,便会把该实例从注册服务列表中剔除(默认是90秒),但是在短时间内丢失大量的实例心跳,这时候EurekaServer会开启自我保护机制,Eureka不会踢出该服务。
自我保护机制的工作机制是:如果在15分钟内超过85%的客户端节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,Eureka Server自动进入自我保护机制,此时会出现以下几种情况:
- Eureka Server不再从注册列表中移除因为长时间没收到心跳而应该过期的服务。
- Eureka Server仍然能够接受新服务的注册和查询请求,但是不会被同步到其它节点上,保证当前节点依然可用。
- 当网络稳定时,当前Eureka Server新的注册信息会被同步到其它节点中。
因此Eureka Server可以很好的应对因网络故障导致部分节点失联的情况,而不会像ZK那样如果有一半不可用的情况会导致整个集群不可用而变成瘫痪。
产生的原因:
在开发测试时,需要频繁地重启微服务实例,但是我们很少会把eureka server一起重启(因为在开发过程中不会修改eureka注册中心),当一分钟内收到的心跳数大量减少时,会触发该保护机制。可以在eureka管理界面看到Renews threshold和Renews(last min),当后者(最后一分钟收到的心跳数)小于前者(心跳阈值)的时候,触发保护机制,会出现红色的警告:
EMERGENCY!EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT.RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEGING EXPIRED JUST TO BE SAFE.
- 1
从警告中可以看到,eureka认为虽然收不到实例的心跳,但它认为实例还是健康的,eureka会保护这些实例,不会把它们从注册表中删掉。
该保护机制的目的是避免网络连接故障,在发生网络故障时,微服务和注册中心之间无法正常通信,但服务本身是健康的,不应该注销该服务,如果eureka因网络故障而把微服务误删了,那即使网络恢复了,该微服务也不会重新注册到eureka server了,因为只有在微服务启动的时候才会发起注册请求,后面只会发送心跳和服务列表请求,这样的话,该实例虽然是运行着,但永远不会被其它服务所感知。所以,eureka server在短时间内丢失过多的客户端心跳时,会进入自我保护模式,该模式下,eureka会保护注册表中的信息,不在注销任何微服务,当网络故障恢复后,eureka会自动退出保护模式。自我保护模式可以让集群更加健壮。
但是我们在开发测试阶段,需要频繁地重启发布,如果触发了保护机制,则旧的服务实例没有被删除,这时请求有可能跑到旧的实例中,而该实例已经关闭了,这就导致请求错误,影响开发测试。所以,在开发测试阶段,我们可以把自我保护模式关闭,只需在eureka server配置文件中加上如下配置即可:
但在生产环境,不会频繁重启,所以,一定要把自我保护机制打开,否则网络一旦终端,就无法恢复。
关闭服务保护
Eureka服务器端添加配置
# 测试时关闭自我保护机制,保证不可用服务及时踢出
eureka.server.enable-self-preservation = false
##剔除失效服务间隔
eureka.server.eviction-interval-timer-in-ms = 2000
- 1
- 2
- 3
- 4
Eureka客户端添加配置
# 心跳检测检测与续约时间
# 测试时将值设置设置小些,保证服务关闭后注册中心能及时踢出服务
###Eureka客户端向服务端发送心跳的时间间隔,单位为秒(客户端告诉服务端自己会按照该规则)
eureka.instance.lease-renewal-interval-in-seconds = 1
####Eureka服务端在收到最后一次心跳之后等待的时间上限,单位为秒,超过则剔除(客户端告诉服务端按照此规则等待自己)
eureka.instance.lease-expiration-duration-in-seconds = 2
- 1
- 2
- 3
- 4
- 5
- 6
文章来源: blog.csdn.net,作者:小毕超,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/qq_43692950/article/details/107500064
- 点赞
- 收藏
- 关注作者
评论(0)