微服务高可用方案
一、微服务的高可用在注册中心、配置中心高可用方案之前,了解一下注册中心的工作原理,下面分为两个部分来解释,一是注册中心和各个微服务的注册表的获取与同步,二是注册中心如何去维护注册表。
1.1、注册表的获取与同步Eureka Server和Eureka Client之间的关系,通过注册表来维护,而注册表的通过Eureka Server集中化管理,每个Client在本地进行注册表的缓存,通过周期性的任务拉取最新的注册表信息。简单的示例图如下。
根据上图所展示的流程,可以了解到注册中心与微服务之间的基本联系的流程:
1.服务A启动时,向Eureka Server注册自己的相关信息
2.当服务B向Eureka Server拉取最新的注册表时,就可以拿到服务A的一台机器注册信息
3.服务A的另外两台机器再去注册,服务B 30s后再次去拉取时,就会得到服务A的三台机器的注册信息
4.服务A、每30s向Eureka Server发送一次心跳信息,表明自己的注册信息还是有效的
以上是注册中心与微服务之间交互的大体流程,在具体的实践中,Eureka Server会提供多级缓存,其中的注册表的信息的获取与同步,又会有细微的差别。
1.Eureka Server的注册表直接基于纯内存,即在内存里维护了一个数据结构。
2.各个服务的注册、服务下线、服务故障,全部会在内存里维护和更新这个注册表。
3.各个服务每隔30秒拉取注册表的时候,Eureka Server就是直接提供内存里存储的有变化的注册表数据给他们就可以了。
4.同样,每隔30秒发起心跳时,也是在这个纯内存的Map数据结构里更新心跳时间。
Eureka Server的注册表是纯内存处理的,因此处理速度会很快,同时提供 readWriteCacheMap 和 readOnlyCacheMap 做缓存,保障了频繁读写不会冲突。示意图如下。
上图介绍了Eureka Server多级缓存的工作原理:
1.当第一台服务A注册时,它的注册信息会更新到内存的注册表中,如果 readWriteCacheMap 中有相应的信息,则过期掉,如果没有则不做操作
2.当服务B去拉取注册表信息时,先找 readOnlyCacheMap ,没有再找 readWriteCacheMap ,再没有就去内存的注册表查找注册信息,查到就更新到 readWriteCacheMap 中,返回给服务B,服务B的注册表中,就会有一台服务A的机器注册信息
3.readOnlyCacheMap 和 readWriteCacheMap 之间的同步是有一个后台的定时任务,每隔30s去同步一次,缓存同步任务
4.第二台服务A注册时,更新内存的注册表,同时把 readWriteCacheMap 过期掉
5.在缓存同步任务执行之前服务B去拉取注册表时,都是从 readOnlyCacheMap 中拿到数据,新的注册表的信息,不会被服务B拿到
6.30s后,缓存同步任务会同步 readWriteCacheMap 和 readOnlyCacheMap 中的数据,把readOnlyCacheMap 中的注册表过期掉,这时服务B就会找 readWriteCacheMap 拿数据,readWriteCacheMap 从内存中拿到数据后缓存,返回给服务B,服务B的注册表中,就会有两台服务A的机器注册信息
7.在下一个30s,缓存同步任务把 readWriteCacheMap 同步到 readOnlyCacheMap 之前, readOnlyCacheMap 没有第二台服务A的注册缓存,因此都是从 readWriteCacheMap 中取到最新数据
注:
readOnlyCacheMap 缓存更新的定时器时间间隔,默认为30秒
readWriteCacheMap 缓存过期时间,默认为 180 秒
由以上流程说明可知,Eureka Server采取了多级缓存策略,同时最新的注册表生效有30s的时延。多级缓存机制的优点是什么:
1.尽可能保证了内存注册表数据不会出现频繁的读写冲突问题。
2.并且进一步保证对Eureka Server的大量请求,都是快速从纯内存走,性能极高。
1.2、注册中心维护微服务的注册表Eureka Client与注册表相关的行为如下所示:
1.服务注册(Registry)——初始化时执行一次,向服务端注册自己服务实例节点信息包括ip、端口、实例名等,基于POST请求。
2.服务续约(renew)——默认每隔30s向服务端PUT一次,保证当前服务节点状态信息实时更新,不被服务端失效剔除。
3.更新已经注册服务列表(fetchRegistry)——默认每隔30s从服务端GET一次增量版本信息,然后和本地比较并合并,保证本地能获取到其他节点最新注册信息。
4.服务下线(cancel)——在服务shutdown的时候,需要及时通知服务端把自己剔除,以避免客户端调用已经下线的服务。