SpringCloud Eureka做服务治理和 Eureka注册中心集群搭建 及 自我保护机制

举报
程序员-上善若水 发表于 2022/06/23 22:30:04 2022/06/23
【摘要】 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集成方式略有不同,请注意下。

  1. 首先新建个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
  1. 然后是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和端口。

  1. 启动Eureka服务
    在启动类的上面添加注解:
@EnableEurekaServer

  
 
  • 1

表明当前是Eureka的注册中心,然后启动项目,然后在浏览器输入localhost:8679,可以看下如下界面证明Eureka注册中心配置成功。
在这里插入图片描述

四、搭建服务提供者

  1. 新建一个springboot项目作为服务提供者,导入pom依赖
<!-- SpringBoot整合eureka客户端 -->
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  1. 配置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调用服务会默认开启了负载均衡。

  1. 然后写一个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连接的时候就可以看到负载均衡轮询效果。

五、服务消费者

  1. 同样新建一个springboot项目作为服务提供者,导入pom依赖
<!-- SpringBoot整合eureka客户端 -->
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  1. 配置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

可以看出这里配置和服务提供者一样。

  1. 配置RestTemplate
	@Bean
	@LoadBalanced
	RestTemplate restTemplate() {
		return new RestTemplate();
	}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

其中@LoadBalanced代表着开启负载均衡。

  1. 消费服务
@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 指向的便是服务提供者的名称+接口名。

  1. 最后还要再启动类上面添加注解
@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自动进入自我保护机制,此时会出现以下几种情况:

  1. Eureka Server不再从注册列表中移除因为长时间没收到心跳而应该过期的服务。
  2. Eureka Server仍然能够接受新服务的注册和查询请求,但是不会被同步到其它节点上,保证当前节点依然可用。
  3. 当网络稳定时,当前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

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。