一、简介
1、提供者与消费者
order-Service (消费者)------------------->user-service(提供者)
order服务调用user服务,order是服务消费者,user是服务提供者。
2、为什么需要Eureka
(1) 传统硬编码调用,不灵活。消费者如何灵活获取提供者信息?
(2)多个服务提供者,怎么调用?
(3)消费者如何获取提供者的健康状态
3、Eureka作用
eureka server(注册中心):记录和管理微服务
eureka client(消费者+提供者):客户
回答2中的问题
4、原理
一个Eureka中分为eureka server和eureka client。其中eureka server是作为服务的注册与发现中心。eureka client既可以作为服务的生产者,又可以作为服务的消费者。具体结构如下图:
上图中我们首先会启动一个或多个Eureka server,这些eureka server同步保留着所有的服务信息。然后我们启动不同的eureka client,向服务端发起服务注册和服务查询。不论我们是向哪个eureka server进行的注册,最终都会同步给所有配置好的eureka server。我们获取的服务信息,也同样都是一致的。
二、简单配置
1、搭建eurake服务
2、服务注册
3、服务发现
4、小结
三、详细介绍
1、在本地启动Eureka服务
Starter: spring-cloud-dependencies 、spring-cloud-starter-netflix-eureka-server
声明:@EnableEurekaServer
注意事项:默认端口8761 Eureka自己不要注册到Eureka
server:
port:8761 #对外提供访问的端口
additionalPorts:18080 #内部启动时占用的端口
eureka:
instance:
lease-expiration-duration-in-seconds:20 #用来修改eureka server默认接受心跳的最大时间 默认是90s。把统计心跳的周期改为20秒,20秒统计一次心跳数
lease-renewal-interval-in-seconds:10 #指定客户端多久向eureka server发送一次心跳 默认是30s。指定10秒发一次心跳,所以一个周期(20秒)就可以发两次心跳,那只要哪怕有一次发送心跳失败,就是1/2=50% < 85%,就会剔除服务实例
prefer-ip-address: true #true,实例以 IP 的形式注册。false,以机器 HOSTNAME 形式注册
hostname:127.0.0.1
client:
register-with-eureka: false #是否向注册中心注册自己
fetch-registry: false #是否从Eureka Server获取注册的服务信息。如果这是一个单点的 Eureka Server,不需要同步其他节点的数据,可以设为false。 false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务 。
heathcheck:
enable:true #默认 Eureka 根据心跳来决定应用的状态,如果是这个属性配置成 true的话,则是会根据 Spring Boot Actuator 来决定,而不是心跳了。
serverUrl:
defaultZone:http://${eureka.instance.hostname}:${server.port}/eureka/ #监控页面
server: #表明是服务端的参数
enable-self-preservation: true #设置为false表示关闭保护模式(关闭后提示见下图红色部分)
eviction-interval-timer-in-ms: 5000 #设置清理的间隔时间,这个时间使用的是毫秒单位(默认是60秒)
2、将服务注册到Eureka Server
Starter: spring-cloud-starter-netflix-eureka-client
声明:@EnableEurekaClient /@EnableDiscoveryClient
其他可以用到的包:
spring-boot-starter-actuator 增加该依赖,可以修改 eureka上的默认描述信息的跳转链接里的信息
同时application.xml增加如下配置
info:
app.name:test
author:yy
server:
port:8765 #对外提供访问的端口
http:
ports:18081 #内部启动时占用的端口
eureka:
instance:
instanceId:${spring.cloud.client.ip-address}:${server.port} #修改eureka上的默认描述信息
prefer-ip-address: true
lease-expiration-duration-in-seconds=10#用来修改eureka server默认接受心跳的最大时间 默认是90s
lease-renewal-interval-in-seconds=5 #指定客户端多久向eureka server发送一次心跳 默认是30s
client:
register-with-eureka: true
fetch-registry: true
heathcheck:
enable:true
initial-instance-info-replication-interval-seconds:10 #第一次初始化延迟注册的时间间隔,默认40s
instance-info-replication-interval-seconds:10 #后续同步注册的时间间隔。复制实例变化信息到eureka服务器所需要的时间间隔(s),默认为30秒
registry-fetch-interval-seconds:10 #指示从eureka服务器获取注册表信息的频率(s)
serverUrl:
defaultZone:http://localhost:8761/eureka/ #监控页面
3、eureka集群搭建
默认情况下,Eureka Server 同时也是 Client, 多个Eureka Server 实例之间可以通过复制的方法, 来实现服务注册表数据的同步。Eureka Client 会缓存服务注册表中的信息,所以 Eureka Client 无须每次调用微服务都要先查询Eureka Server,能有效地缓解Eureka Server的压力,而且即使所有的Eureka Server节点都宕掉,Client 依然可以根据缓存中信息找到服务提供者。
1)为方便观察,host文件中增加如下配置:
127.0.0.1 eureka8761.com
127.0.0.1 eureka8751.com
2) 选中eureka Server服务,鼠标右键 Copy Configuration 拷贝一个服务
3)eureka Server修改配置文件,或选中服务,Edit Configuration,增加如下配置:
-Deureka.instance.hostname=eureka8761.com
-Deureka.client.serviceUrl.defaultZone=http://eureka8751.com:8751/erueka #注,defaultZone配置的不是自己,是另一个集群服务。
-Deureka.instance.hostname=eureka8751.com
-Deureka.client.serviceUrl.defaultZone=http://eureka8761.com:8761/erueka
4)eureka Client 修改配置文件,或选中服务,Edit Configuration,增加如下配置:
Deureka.client.serviceUrl.defaultZone=http://eureka8761.com:8761/erueka,http://eureka8751.com:8751/erueka
4、Eureka自我保护机制
微服务会周期性(默认30秒 eureka.instance.lease-renewal-interval-in-seconds)地向Eureka Server 发送心跳以维持自己的注册状态,如果Eureka Server 在一定时间(默认90秒eureka.instance.lease-expiration-duration-in-seconds)没有接受到某个微服务实例的心跳,Eureka Server 将会注销该实例。但是当网络分区故障发生时,微服务与Eureka Server之间无法正常通信,而微服务本身是正常运行的,此时不应该移除这个微服务,所以引入了自我保护机制.
Eureka自我保护机制(雪崩保护):某个微服务本身健康,但是因为断电等问题,导致不可访问,此时EurekaServer(在短时间内丢失过多客户端时)就会保护服务注册表中的信息,不再删除服务注册表中的数据。当故障恢复后(收到的心跳数重新恢复的阈值以上时),Eureka Server自动退出自我保护模式。
Eureka Server 在运行期间会去统计心跳失败比例在 15 分钟之内是否低于 85%,如果低于 85%,Eureka Server 会将这些实例保护起来,让这些实例不会过期,但是在保护期内如果服务刚好这个服务提供者非正常下线了,此时服务消费者就会拿到一个无效的服务实例,此时会调用失败,对于这个问题需要服务消费者端要有一些容错机制,如重试,断路器等。自我保护模式被激活的条件是:Renews (last min) < Renews threshold。自我保护被激活后,提示信息见下图。
当Eureka Server自动进入自我保护机制后,此时会出现以下几种情况:
1️⃣. Eureka Server不再从注册列表中移除因为长时间没收到心跳而应该过期的服务;
2️⃣. Eureka Server仍然能够接受新服务的注册和查询请求,但是不会被同步到其它节点上,保证当前节点依然可用;
3️⃣. 当网络稳定时,当前Eureka Server新的注册信息会被同步到其它节点中.
以上3点是从其他博客(https://blog.csdn.net/syc000666/article/details/95904299)看到的,但是第2点,没验证出来,可能是理解有问题。---------TODO
Renews threshold:Eureka Server 期望每分钟收到客户端实例续约的总数。
(阈值计算四舍五入)renews threshold=(1+2×n)*0.85。 (不管集群中有多少个server相互注册,都不会对阈值构成影响,n 为client个数,不包含server。-----有歧义,看其他博客,有的计算方法server注册时,也会算进去,也就是2*(server+client)*0.85)
自我保护系数:eureka.server.renewal-percent-threshold=0.85
Renews (last min) :Eureka Server 最后 1 分钟收到客户端心跳的总数。
Renews (last min) =2*(application列表里的实例心跳之和)。如果server也注册了自己,那么心跳也算在内,如果未注册自己,则不算。
此时按每个client里的 eureka.instance.lease-renewal-interval-in-seconds=30配置计算心跳,再乘以2。
测试案例:
一、单体
(1)启动eurekaServer,并注册自己。心跳配置为1分钟2次( lease-expiration-duration-in-seconds:60 eureka.instance.lease-renewal-interval-in-seconds=30) 。此时Renews threshold=(1+2×0)*0.85=1 ,Renews (last min) =2*2=4
(2)再 启动一个client实例注册到server, 心跳也配置为1分钟2次。此时Renews threshold=(1+2×1)*0.85 =3 ,Renews (last min) =2*(2+2)=8
二、集群 (注意集群配置方式是相互注册,server defaultZone 不配置自己,否则测试数据不正确。经测试,集群的心跳是所有集群中单体的总和。)
(1)启动两个eureka集群,并都注册自己到server,心跳都配置为1分钟2次。刚启动时,Applition里只有彼此的一个服务,此时Renews threshold= 2,Renews (last min) =0。之后,Applition里只有集群的两个服务, 此时Renews threshold= 4, Renews (last min) =0 。稳定后,Renews threshold=(1+2×0)*0.85 =1 ,Renews (last min) =2+2=4(集群的每个单体都显示为4,总和为8)
(2)再启动一个client实例注册到server,心跳也置为1分钟3次。此时Renews threshold=(1+2×1)*0.85 =3(注意,一定等注册中心server启动后,再启动client实例,否则注册中心统计不上) ,Renews (last min) =2+2+3=7 (集群的每个单体都显示为7,总和为14)
(3)关闭一个eureka集群,此时Renews threshold依旧为3,Renews (last min) 先变为5(死亡的server不发送心跳 ,此时application列表里也没有了该实例),稳定后 Renews (last min) 又变为3(还存在的server无法向死亡的server注册,无法发送自己的心跳,无法同步信息,此时application里只剩下一个client实例),此时触发 自我保护机制 。
(4)之后把client实例的心跳改为1分钟6次,并且修改配置,只注册到活着的server上,再启动,此时Renews (last min) =6,自我保护机制失效,此时server控制台可以看到,Application列表里只有client实例,两个server都没有。
不触发自我保护机制,解决方式有4种:
1)关闭自我保护模式(eureka.server.enable-self-preservation设为false),不推荐。(关闭后,提示信息见下图)
2)降低renewalPercentThreshold的比例(eureka.server.renewal-percent-threshold设置为0.5以下,比如0.49),不推荐。
3) lease-expiration-duration-in-seconds:=1 eureka.instance.lease-renewal-interval-in-seconds=2 修改这两个参数的比例,如1,2
4)部署多个 Eureka Server 并开启其客户端行为(eureka.client.register-with-eureka不要设为false,默认为true),推荐。
注释:
1)对于3.3,对于eureka Server单体, defaultZone配置的是自己的ip端口,对于集群,为什么 defaultZone配置的不是两个集群的地址,而是另一个集群实例?------相互注册是为了同步客户端的注册信息,clientA和clientB分别往serverA、serverB两台server注册,如果不相互注册那serverA上就没有clientB的注册信息。
2)对于集群,如果 defaultZone配置的是两个集群的地址,有什么问题? ---DS Replicas里会展示两个集群信息。默认情况下,Eureka Server 同时也是 Client,且不将自己算入Renews threshold内,如果都配置了,则会将自己算入Renews threshold内。
3)对于3.4,defaultZone配置的是两个集群的地址,配置一个有什么问题?----
4、一些其他参数:
https://www.bbsmax.com/A/o75N9OgNJW/ https://cloud.tencent.com/developer/article/1145780
eureka:
server:
enable-self-preservation: true #自我保护模式,当出现网络分区故障、频繁的开启关闭客户端、eureka在短时间内丢失过多客户端时,会进入自我保护模式,即一个服务长时间没有发送心跳,eureka也不会将其删除,默认为true
eviction-interval-timer-in-ms: 60000 #eureka server清理无效节点的时间间隔,默认60000毫秒,即60秒
renewal-threshold-update-interval-ms: 15 * 60 * 1000 #阈值更新的时间间隔,单位为毫秒,默认为15 * 60 * 1000
renewal-percent-threshold: 0.85 #阈值因子,默认是0.85,如果阈值比最小值大,则自我保护模式开启 delta-
retention-timer-interval-in-ms: 30000 #清理任务程序被唤醒的时间间隔,清理过期的增量信息,单位为毫秒,默认为30 * 1000
wait-time-in-ms-when-sync-empty #服务间请求的等待时长 。在Eureka服务器获取不到集群里对等服务器上的实例时,需要等待的时间(分钟),默认为5 。
peer-eureka-nodes-update-interval-ms: 10000 #同步时长
eureka:
instance:
lease-expiration-duration-in-seconds 指示eureka服务器在删除此实例之前收到最后一次心跳之后等待的时间(s),默认为90 。 告诉服务端,如果我90s之内没有给你发心跳,就代表我“死”了,请将我踢掉。
prefer-ip-address eureka 监控界面 Status 下的跳转到其监控页面网址的形式。当 hostname 和 prefer-ip-address 都没有配置,则访问 主机名:服务名:端口号:;当配置了 hostname 而没有配置 prefer-ip-address,则访问 hostname:服务名:端口号:;如果配置了 prefer-ip-address,则访问 ipAddress:服务名:端口号:;
lease-renewal-interval-in-seconds=5 #指定客户端多久向eureka server发送一次心跳 默认是30s
5、其他问题:
1)Eureka 延迟注册不生效
默认情况下,配置了延迟注册的时间并不会生效,因为事件监听默认是true,服务启动之后就会立刻注册到 Eureka Server。如果需要延迟注册生效,必须 eureka.client.healthcheck.enabled、eureka.client.onDemandUpdateStatusChange 都为false。即便我们把所有途径都封死了,但是发送心跳的线程仍然会去注册,所以这个延迟注册的时间最多也不会超过 30 秒,即便配置的延迟时间超过 30 秒。
四、原理
https://blog.csdn.net/u010883443/article/details/108470758 Eureka源码
https://www.cnblogs.com/StarkBrothers/p/11974026.html 部署eureka集群时defaultZone中为什么必须包含路径/eureka