Eureka使用的是服务消费模式以及服务注册模式,本文来详细讲解。
1. 服务消费者模式
Eureka使用的是服务消费者模式。
获取服务:
- 消费者启动的时候,使用服务别名,会发送一个rest请求到服务注册中心获取对应的服务信息,然后会缓存到本地jvm客户端中,同时客户端每隔30秒从服务器上更新一次。
- 可以通过 fetch-inte vall-seconds=30参数进行修以通过eureka.client .registry该参数默认值为30, 单位为秒。
服务下线:
- 在系统运行过程中必然会面临关闭或重启服务的某个实例的情况,在服务关闭期有我们自然不希望客户端会继续调用关闭了的实例。所以在客户端程序中,当服务实例过正常的关闭操作时,它会触发一个服务下线的REST请求给Eureka Server, 告诉服务日中心:“我要下线了”。服务端在接收到请求之后,将该服务状态置为下线(DOWN),井该下线事件传播出去。
2.服务注册模式
失效剔除:
- 有些时候,我们的服务实例并不一定会正常下线,可能由于内存溢出、网络故障气因使得服务不能正常工作,而服务注册中心并未收到“服务下线”的请求。为了从服务表中将这些无法提供服务的实例剔除,Eureka Server 在启动的时候会创建一个定时任多默认每隔一一段时间(默认为60秒)将当前清单中超时(默认为90秒)没有续约的服务除出去。
自我保护:
- 默认情况下,EurekaClient会定时向EurekaServer端发送心跳,如果EurekaServer在一定时间内没有收到EurekaClient发送的心跳,便会把该实例从注册服务列表中剔除(默认是90秒),但是在短时间内丢失大量的实例心跳,这时候EurekaServer会开启自我保护机制,Eureka不会踢出该服务。
产生的原因:
- 在开发测试时,需要频繁地重启微服务实例,但是我们很少会把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.)
从警告中可以看到,eureka认为虽然收不到实例的心跳,但它认为实例还是健康的,eureka会保护这些实例,不会把它们从注册表中删掉。
该保护机制的目的是避免网络连接故障,在发生网络故障时,微服务和注册中心之间无法正常通信,但服务本身是健康的,不应该注销该服务,如果eureka因网络故障而把微服务误删了,那即使网络恢复了,该微服务也不会重新注册到eureka server了,因为只有在微服务启动的时候才会发起注册请求,后面只会发送心跳和服务列表请求,这样的话,该实例虽然是运行着,但永远不会被其它服务所感知。所以,eureka server在短时间内丢失过多的客户端心跳时,会进入自我保护模式,该模式下,eureka会保护注册表中的信息,不在注销任何微服务,当网络故障恢复后,eureka会自动退出保护模式。自我保护模式可以让集群更加健壮。
但是我们在开发测试阶段,需要频繁地重启发布,如果触发了保护机制,则旧的服务实例没有被删除,这时请求有可能跑到旧的实例中,而该实例已经关闭了,这就导致请求错误,影响开发测试。所以,在开发测试阶段,我们可以把自我保护模式关闭。但在生产环境,不会频繁重启,所以,一定要把自我保护机制打开,否则网络一旦中断,就无法恢复。
当然关于自我保护还有很多个性化配置,这里不详细说明。
注意考虑网络不可达情况下:调用接口幂等、重试、补偿等。
3. 如何关闭服务保护
3.1 Eureka服务器端配置
###服务端口号 server: port: 8100 ##定义服务名称 spring: application: name: eureka-server-01 eureka: instance: ###注册中心ip地址 hostname: 127.0.0.1 client: serviceUrl: ##注册地址 defaultZone: http://${eureka.instance.hostname}:8100/eureka/ ####因为自己是注册中心,是否需要将自己注册给自己的注册中心(集群的时候是需要是为true) register-with-eureka: false ###因为自己是注册中心, 不需要去检索服务信息 fetch-registry: false server: # 测试时关闭自我保护机制,保证不可用服务及时踢出 enable-self-preservation: false eviction-interval-timer-in-ms: 2000
核心配置:
server: # 测试时关闭自我保护机制,保证不可用服务及时踢出 enable-self-preservation: false ##剔除失效服务间隔 eviction-interval-timer-in-ms: 2000
3.2 Eureka客户端配置
###订单服务的端口号 server: port: 8001 ###服务别名----服务注册到注册中心名称 spring: application: name: eureka-service-b eureka: client: service-url: ##### 当前会员服务注册到eureka服务地址 # defaultZone: http://localhost:8101/eureka,http://localhost:8102/eureka defaultZone: http://localhost:8100/eureka ### 需要将我的服务注册到eureka上 register-with-eureka: true ####需要检索服务 fetch-registry: true registry-fetch-interval-seconds: 30 # 心跳检测检测与续约时间 # 测试时将值设置设置小些,保证服务关闭后注册中心能及时踢出服务 instance: ###Eureka客户端向服务端发送心跳的时间间隔,单位为秒(客户端告诉服务端自己会按照该规则) lease-renewal-interval-in-seconds: 1 ####Eureka服务端在收到最后一次心跳之后等待的时间上限,单位为秒,超过则剔除(客户端告诉服务端按照此规则等待自己) lease-expiration-duration-in-seconds: 2
核心配置:
# 心跳检测检测与续约时间 # 测试时将值设置设置小些,保证服务关闭后注册中心能及时踢出服务 instance: ###Eureka客户端向服务端发送心跳的时间间隔,单位为秒(客户端告诉服务端自己会按照该规则) lease-renewal-interval-in-seconds: 1 ####Eureka服务端在收到最后一次心跳之后等待的时间上限,单位为秒,超过则剔除(客户端告诉服务端按照此规则等待自己) lease-expiration-duration-in-seconds: 2
总结