服务自保由两个开关进行控制。
EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEYRE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.
如图 2.13 所示红色字体,就是服务自保开启后的警告,意思是说,挂掉的服务有可能会被错误地当作UP,(在一定时间内)续约成功的节点个数占已注册总服务的比值,已经低于限定值,因此所有节点都不会过期,服务自保开启。
图 2.13
这是一个服务自保的自动触发开关,简单来说,服务自保机制会检查过去 15 分钟以内,所有成功续约的节点,占所有注册节点的比例,如果低于一个限定值(比如 85%)就开启服务自保模式。
服务自保模式往往是为了应对短暂的网络环境问题,在理想情况下服务节点的续约成功率应该接近 100%,如果突然发生网络问题,比如一部分机房无法连接到注册中心,这时候续约成功率有可能大幅降低。但考虑到Eureka采用客户端的服务发现模式,客户端手里有所有节点的地址,如果服务节点只是因为网络原因无法续约,但其自身服务是可用的,那么客户端仍然可以成功发起调用请求。这样就避免了被服务剔除给错杀。手动开关:
如下代码所示,是服务自保的总闸,以下配置将强制关闭服务自保,即便上面的自动开关被触发,也不能开启自保功能,当配置了,就不会出现自我保护意识了。
eureka.server.enable-self-preservation=false
●服务续约
在了解服务续约之前,我们先来理一理心跳、续约和剔除之间的关系。都紧紧围绕在注册中心里的服务同步时间,如图 2.14 所示。
图 2.14
续约和心跳的关系,服务续约分为两步:
第一步是将服务节点的状态同步到注册中心,意思是通知注册中心还可以继续工作,这一步需要借助客户端的心跳功能来主动发送。
第二步当心跳包到达注册中心的时候,那就要看注册中心有没有心动的感觉了,他有一套判别机制,来判定当前的续约心跳是否合理。并根据判断结果修改当前instance在注册中心记录的同步时间。
发送Renew请求:
服务续约请求,如图 2.15 所示。
图 2.15
在前面的章节里我们讲到过,客户端有一个DiscoverClient类,它是所有操作的门面入口。所以续约服务就从这个类的renew方法开始。
●发送心跳
服务续约借助心跳来实现,因此发给注册中心的参数和上一小节的心跳部分写到的一样,两个重要参数分别是服务的状态(UP)和lastDirtyTimeStamp,如果续约成功,注册中心则会返回 200 的HTTP code,如果续约不成功,注册中心返回 404,这里的404 并不是说没有找到注册中心的地址,而是注册中心认为当前服务节点并不存在。这个时候再怎么续约也不灵验了,客户端需要触发一次重新注册操作。在重新注册之前,客户端会做下面两个小操作,然后再主动调用服务册流程。
设置lastDirtyTimeStamp:
由于重新注册意味着服务节点和注册中心的信息不同步,因此需要将当前系统时间更新到“lastDirtyTimeStamp”标记自己为脏节点。当注册成功的时候,清除脏节点标记,但是lastDirtyTimeStamp不会清除,因为这个属性将会在后面的服务续约中作为参数发给注册中心,以便服务中心判断节点的同步状态。
●注册中心续约校验
考验注册中心灵验不灵验的时候到了,注册中心开放了一系列的HTTP接口,来接受四面八方的各种请求,他们都放在com.netflix.eureka.resources这个包下。只要客户端路径找对了,注册中心什么都能帮你办到,如图 2.16 所示。
图 2.16
接受请求:
服务节点说:“万能的注册中心,请赐予我永生”。注册中心:“想得美,从现在算到下一次心跳间隔时间,如果你没来renew,就当你死了”。注册中心此时会做几样简单的例行检查,如果没有通过,则通通返回 404,不接受申辩。
脏数据校验:
如果续约校验没问题,接下来就要进行脏数据检查。到了服务续约最难的地方了,脏数据校验逻辑之复杂,如同这皇冠上的明珠。往细了说,就是当客户端发来的lastDirtyTimeStamp,晚于注册中心保存的lastDirtyTimeStamp时(每个节点在中心都有一个脏数据时间),说明在从服务节点上次注册到这次续约之间,发生了注册中心不知道的事儿(数据不同步)。这可不行,这搞得注册中心的工作不好有序开展,回去重新注册吧。续约不通过,返回 404。
●集群的搭建
参考【cloud_orders】工程模块创建cloud-eureka-server7001,cloud-eureka-se rver7002,cloud-eureka-server7003,如图 2.17所示。
图 2.17
修改当前C:\Windows\System32\drivers\etc\hosts文件,配置上对应的请求地址名,配置如下所示。
行修改 7001、7002、7003 配置的地址,并让 7001、7002、7003 模块工程相互注册,相互守望
如上述配置描述:
●server.port 配置端口号
●eurek.instance.hostname: eureka7002.com eureka服务端的实例名字
●eurek.instanceclient.register-with-eureka: false表识不向注册中心注册自己
●eurek.instanceclient.fetch-registry: false表示自己就是注册中心,职责是维护服务实例,并不需要去检索服务
●eurek.instanceclient.service-url.defaultZone: 设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址。
启动 7001、7002、7003 服务,执行地址,如图 2.18 所示。
图 2.18
支付 8001,订单 80 注入Eureka集群中,修改(80,8001)application.yml文件配置如下
如上配置描述如下所示:
●eureka.client.register-with-eureka: true 表示是否将自己注入Eureka服务中,默认为true
●eureka.client.fetchRegistry: true 单点无所谓,集群必须设置为true,才能配置Ribbon使用负载均衡
●eureka.client.service-url.defaultZone: 集群配置
先启动 7001,7002,7003 然后在启动 8001 和 80 工程执行地址,如图 2.19 所示。
图 2.19
执行http://localhost/consumer/payment/getPaymentById/31该地址,如图2.20所示。
图 2.20
本章讲解了关于心跳检测和服务剔除的知识,包括消费者如何进行调用服务者的请求与心跳检测的作用、心跳包含的内容以及控制参数、注册中心服务剔除操作的核心流程等。
1. 描述什么是注册中心?
2. 描述心跳检测是什么运行的?
3. 服务续约是什么?