查看原文
其他

集群环境下注册中心宕机后的高可用实践

中国光大银行 中国光大银行科技创新实验室 2024-01-09

注册中心作为微服务最基础、最核心的组件,通过服务注册与服务发现机制,注册中心为注册在其上的微服务提供服务列表,注册中心的可用性在微服务架构中要求极高。在实际开发中,通过多中心、多集群部署方式来提高注册中心的可用性,但是也无法做到100%可用。在极端情况下,注册中心宕机时,该如何将影响降到最低呢?



注册中心的职责

我们先来看下注册中心的职责,下面一张图就可以解释注册中心的主要职责。

服务端/provider:对外提供后台服务方,将自己的服务信息注册到注册中心。


客户端/consumer:从注册中心获取远程服务的注册信息,并通过负载均衡策略,选取服务进行远程调用。


注册中心:用于服务端/provider进行服务的注册,客户端/consumer获取服务列表并调用。


我们可以清晰的看到,注册中心在微服务架构中的重要作用,在注册中心宕机时,客户端/consumer以及服务端/provider失去与注册中心的连接,如果没有任何服务列表缓存的情况下,服务之间的调用会受到影响。



Spring Cloud 的服务注册与发现

为了更好的阐述注册中心不可用带来的问题,我们看看Spring Cloud的服务注册发现是怎么做的。我行使用Consul作为微服务注册中心,我们就以Consul作为注册中心源码为例进行说明。


2.1

 服务注册 

服务注册的源码在注册的过程中主要做了三件事情:


  1. 通过ConsulClient发起服务注册的操作,最终将通过http请求发送该服务的注册信息至Consul,完成服务注册。


  2. 根据健康检查的配置,默认为Consul定时向各个应用端点发送http请求的方式来判断服务是否存活,可以通过设置spring.cloud.consul.discovery.healthCheckUrl设置自定义的端点。也可以通过设置spring.cloud.consul.discovery.heartbeat.enable=true将健康检查方式设置为由应用向Consul定时发送心跳的方式。


  3. 服务注册发生异常时,会根据配置FailFast的取值,决定是否抛出异常,当FailFast为false时,不抛出异常,服务可以不依赖Consul启动。


2.2

 服务发现 

服务发现的源码在发现服务列表的过程中主要做一件事情:

  1. 从Consul获取所需要的服务名对应的服务列表。


2.3

 服务调用 

目前,基于SpringCloud微服务、Consul注册中心的微服务体系,微服务仅有LoadBanlancer提供的缓存作为服务列表缓存,其为过期失效机制,仅在过期时间内有效,服务调用时,优先获取该负载均衡缓存,负载均衡缓存失效则访问注册中心获取服务列表。因此,在注册中心宕机的情况下,无降级的服务列表缓存供服务调用,即存在注册中心Consul宕机时,服务之间无法调用的问题。



集群环境下注册中心宕机后的高可用实践

为了解决服务之间无法调用的问题,在原有负载均衡缓存的基础上,提出一种本地服务列表内存缓存、本地服务列表文件缓存的多级缓存机制,作为访问注册中心异常时的服务列表降级策略。第一次调用某服务时,对本地服务列表内存缓存进行初始化,同时异步写入本地服务列表文件缓存,同时开启定时调度定时更新本地服务列表内存缓存和文件缓存,做到与注册中心的服务同步。当注册中心宕机时,获取注册中心的服务列表异常,则降级为使用本地服务列表内存缓存进程服务调用,当注册中心宕机仍需要对微服务进行重启时,启动加载服务列表文件缓存作为初始化的服务列表。综上,在不影响原有调用链路的基础上,保障了注册中心宕机场景下服务调用正常。


具体分以下3种场景阐述注册中心宕机下的服务异常情况:

  1. 服务运行中注册中心宕机的场景

  2. 注册中心宕机时需要启动新服务的场景

  3. 注册中心宕机时需要重启服务的场景


3.1

 服务运行中注册中心宕机的场景 

微服务运行中注册中心宕机的场景,是比较常见的一种情况,此时服务已经在注册中心注册过,但是注册中心宕机后,微服务与注册中心之间无法建立通信,请求Consul注册中心获取服务列表的请求都会异常,因此捕获该异常,降级为从本地服务列表缓存获取服务列表的方式,进行服务的调用,保证运行中的服务节点间的调用在注册中心宕机时不受影响。


3.2

 注册中心宕机时启动新服务的场景 

在注册中心宕机的情况下,可能有服务扩容或者需要重新启动的场景,服务在启动时向注册中心Consul发起服务注册时会调用异常,因此在注册中心宕机的情况下需要做到服务不强依赖注册中心启动。根据服务注册源码分析可知,服务注册发生异常时,会根据配置FailFast的取值,决定是否抛出异常,在FailFast为true的情况下(默认),服务会抛出异常导致启动失败,而当FailFast为false的情况下,服务仅输出一段warn日志,不影响服务的启动。


因此在注册中心宕机的情况下,针对新启动的服务(如容器环境下扩容),可以通过修改spring.cloud.consul.config.fail-fast和spring.cloud.consul.discovery.fail-fast配置为false让应用先启动,由于注册中心不可用,新启动的服务获取不到可用的服务列表,因此服务发现不可用。但是当Consul注册中心恢复后,微服务与注册中心重新建立通信,服务注册发现和服务之间的调用均会恢复正常不受影响。


3.3

 注册中心宕机时需要重启服务的场景 

注册中心宕机时需要重启服务的场景,这里指的是注册中心宕机期间,如果有必要对服务进行重启的情况(如容器环境下服务重启)。2.3.2中阐述了将FailFast配置设置为false可以使服务不依赖注册中心进行重启。重启后,由于本地服务列表缓存随着服务的重启而失效,而注册中心宕机期间,服务发现的请求又会失败,因此需要将本地服务列表内存缓存升级为持久化的缓存,如本地服务列表文件缓存的形式,本地服务列表文件缓存与本地服务列表内存缓存内容一致,采用异步写入的形式进行数据的同步和更新。服务重启时,加载本地服务列表文件缓存的内容到内存中,保证Consul宕机期间,服务重启后调用正常。



小结

综上,是集群环境下注册中心Consul宕机后的高可用方案实践。为了保证注册中心宕机时服务之间的可用性,在服务本地建立一套本地服务列表内存缓存加本地服务列表文件缓存的机制,该缓存通过定时拉取注册中心的服务列表的方式做更新,与注册中心服务列表保持同步。在注册中心不可用时,即服务从Consul获取服务列表失败,则降级为获取本地服务列表内存缓存的方式进行服务间的通信。此时,如果有必要对服务进行重启,需要将服务的Consul配置的FailFast属性设置为false,使服务不依赖注册中心Consul启动正常。并且,在服务重启时加载本地服务列表文件缓存的内容,该列表保存的是服务重启前最后一次更新的服务列表,可以保证重启后服务之间正常调用。综上,在不影响正常调用链路的情况下,可以做到注册中心Consul宕机恢复过程中的高可用。


作者 | 王海涛 时丹

视觉 | 王朋玉

统筹 | 郑    洁

继续滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存