OceaBase开发者大会落地上海!4月20日共同探索数据库前沿趋势!报名戳 了解详情
写点什么

踩坑总结:鹅厂小哥教你注册中心宕机后正确的处理姿势

  • 2020-12-26
  • 本文字数:2869 字

    阅读完需:约 9 分钟

踩坑总结:鹅厂小哥教你注册中心宕机后正确的处理姿势

微服务化是当前的一大趋势,注册中心既是微服务最基础的组件,也是最核心的组件,它为客户端提供所有可调用的服务列表。也正因如此,注册中心的可用性在微服务架构中要求极高。在实际开发中,虽然我们可以通过一些手段不断的在提高注册中心的可用性,但也无法保证注册中心 SLA (Service Level Agreement,服务级别协议)100%的可用性。既然这样,那么当注册中心宕机不可用时,我们应该如何做才能减轻影响呢?


注册中心的职责


在分析注册中心宕机带来的影响前,我们先来看下注册中心的职责,下面一张图就可以解释注册中心的主要职责。



  • 注册中心:用于服务端注册远程服务以及客户端发现服务。

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

  • 客户端:从注册中心获取远程服务的注册信息,然后进行远程过程调用。


可以很清晰的看到,在注册中心宕机时,服务注册以及服务发现和服务节点推送都会受到影响,在没有任何缓存的情况下,服务之间的调用都会受到影响。


Spring Cloud 的服务注册与发现


为了更好的阐述注册中心不可用带来的问题,我们先看看 Spring Cloud 的服务注册发现是怎么做的。这里我们以 Spring Cloud Consul 的代码为例。


服务注册


public void register(ConsulRegistration reg) {    log.info("Registering service with consul: " + reg.getService());    try {      client.agentServiceRegister(reg.getService(), properties.getAclToken());      if (heartbeatProperties.isEnabled() && ttlScheduler != null) {        ttlScheduler.add(reg.getInstanceId());      }    }    catch (ConsulException e) {      if (this.properties.isFailFast()) {        log.error("Error registering service with consul: " + reg.getService(), e);        ReflectionUtils.rethrowRuntimeException(e);      }      log.warn("Failfast is false. Error registering service with consul: " + reg.getService(), e);    }}
复制代码


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


  1. 使用 Consul Client SDK 发起服务注册的操作。

  2. 使用定时任务定时发起心跳。

  3. 服务注册发生异常时,会根据配置 FailFast 的取值抛出异常。


服务发现


private List<ConsulServer> getServers() {    if (this.client == null) {      return Collections.emptyList();    }    String tag = getTag(); // null is ok    Response<List<HealthService>> response = this.client.getHealthServices(        this.serviceId, tag, this.properties.isQueryPassing(),        createQueryParamsForClientRequest(), this.properties.getAclToken());    if (response.getValue() == null || response.getValue().isEmpty()) {      return Collections.emptyList();    }    return transformResponse(response.getValue());  }
/** * Transforms the response from Consul in to a list of usable {@link ConsulServer}s. * * @param healthServices the initial list of servers from Consul. Guaranteed to be non-empty list * @return ConsulServer instances * @see ConsulServer#ConsulServer(HealthService) */protected List<ConsulServer> transformResponse(List<HealthService> healthServices) { List<ConsulServer> servers = new ArrayList<>(); for (HealthService service : healthServices) { ConsulServer server = new ConsulServer(service); if (server.getMetadata().containsKey(this.properties.getDefaultZoneMetadataName())) { server.setZone(server.getMetadata().get(this.properties.getDefaultZoneMetadataName())); } servers.add(server); } return servers; }
复制代码


服务发现的部分则更加简单,使用 Consul Client 获取服务名节点。我们已经清楚服务注册和发现的处理流程,再来看看宕机场景下的服务注册和发现。


注册中心宕机下的服务注册和发现


这里我们分 3 种场景来阐述注册中心宕机下服务的异常情况:


  • 新启动的服务下的异常

  • 运行中的服务的异常

  • 运行中且重启过的服务


1. 新启动的服务的异常


  • 服务注册


在注册中心宕机的情况下,用户可能有服务扩容或者需要启动新服务的诉求,服务在启动的时候会在 Consul Client 发起服务注册调用时异常,在 FailFast 开启的情况下(默认开启),服务会抛出异常,同时服务会启动失败,而当 FailFast 没有被打开的情况下,服务仅输出一段 warn 日志,不影响服务的启动。


那么在注册中心宕机的情况下,针对服务扩容或者新启动的服务,可以通过关闭 FailFast 让应用启动,后续通过心跳进行自动注册,来减轻对服务的影响。


  • 服务发现


由于注册中心连接不上,且新启动的服务没有任何调用方的服务节点的数据源可以读取数据,因此服务发现不可用。


2. 运行中的服务的异常


  • 服务注册


对于运行中的服务,服务已经注册成功,但宕机期间所有的心跳请求都会失败。


  • 服务发现


注册中心宕机期间,服务发现的请求会失败。


这里我们可以通过建立 cache 的方式来做降级处理,建立内存 cache+文件 cache 的方式。在发现注册中心不可用时使用内存 cache 中的数据,内存 cache 无数据则访问文件 cache。通过缓存的降级逻辑,当前运行中的服务节点间的调用不受影响,但对于新启动的节点以及宕机或者下线的节点存在无法感知的情况。


3. 运行中且重启过的服务


运行中且重启过的服务,这里指的是注册中心宕机期间,正常的服务被重启。


  • 服务注册


宕机期间所有的 HeartBeat 请求以及服务注册的请求都会失败。


服务重启时可以通过关闭 fail fast 进行服务的启动。这样这个节点能正常处理上游的流量。


  • 服务发现


注册中心宕机期间,服务发现的请求会失败。


通过内存 cache+文件 cache 的方式来进行降级处理。服务发现过程中,发现注册中心不可用,则尝试使用内存 cache 的数据,但内存 cache 中的数据为空,则尝试使用本地文件数据进行恢复。


注册中心恢复中服务发现的异常


通过上述的一些降级方法,能够有效的降低注册中心异常对业务的影响。那么这样就够了吗?我们再来看一个注册中心恢复时的异常 case:


  1. 注册中心异常。

  2. 服务调用方调用注册中心异常,则降级使用 cache 中的数据。

  3. 注册中心恢复,此时大量的节点可能还未发起定时心跳的请求,因此所有的服务节点状态都变成了不健康的状态(Consul Health Check 配置 TTL check 的场景)。

  4. 服务调用方再次从注册中心拉取新的数据,但是所有节点都是不健康的节点。

  5. 服务调用失败。


针对这种场景,应该如何做呢?我们可以通过设置一个冷静期,在 Consul Client 发起拉取服务节点成功时,从以前使用 Cache 的降级数据到使用真实的服务节点数据前,等待两个心跳周期,等待期间都使用 Cache 数据,等被调方能正常完成心跳,更新其节点的健康状态后在使用真实的数据。



头图:Unsplash

作者:张艺辰

原文采坑总结:鹅厂小哥教你注册中心宕机后正确的处理姿势

来源:腾讯云中间件 - 微信公众号 [ID:gh_6ea1bc2dd5fd]

转载:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

2020-12-26 19:201899

评论

发布
暂无评论
发现更多内容

大杀四方!腾讯强推599页Netty进阶神技,彻底解析Netty

Geek_0c76c3

Java 数据库 程序员 架构 开发

字节奋战8年,回头一看只剩下这份1857页的算法笔记了

Geek_0c76c3

Java 数据库 开源 程序员 开发

【Go】Go 操作 excel 代码封装

非晓为骁

Excel go语言

肝下50万字的《Linux内核精通》笔记,你的底层原理水平将从入门到入魔【建议收藏】

简说Linux内核

内存管理 嵌入式 Linux内核 进程管理 驱动开发

金三银四跳槽季,美团、字节、阿里、腾讯Java面经,终入字节

Geek_0c76c3

Java 数据库 开源 程序员 开发

精彩演讲推荐|智能化变更防控方法、架构与组织实践

TRaaS

双活数据中心建设要点

穿过生命散发芬芳

10月月更 双数据中心

ironSource ROAS 智能优化工具大升级,用户现可查看每日 KPI 数据及趋势走向

Geek_2d6073

真的香!Github一夜爆火被各大厂要求直接下架的面试题库也太全了

Geek_0c76c3

Java 数据库 开源 程序员 开发

TDengine | taosdump的使用方法和注意事项

TDengine

数据库 tdengine 开源 时序数据库 taosdump

vue组件通信6种方式总结(常问知识点)

bb_xiaxia1998

Vue

ConcurrentDictionary<T,V> 的这两个操作不是原子性的

有态度的马甲

太全了!华为大神珍藏版SpringBoot全优笔记,首次分享

Geek_0c76c3

Java 数据库 开源 程序员 架构

【导航】ESP32-C3 入门教程目录 【快速跳转】

矜辰所致

目录 ESP32-C3 10月月更

阿里大佬手码的SpringCloud+Alibaba笔记开源了,堪称保姆式教学

Geek_0c76c3

Java 数据库 开源 程序员 开发

Java后端没这些东西都不敢跳!对标阿里P7技术路线你值得拥有

Geek_0c76c3

Java 数据库 程序员 架构 开发

GitHub star过万!仅靠这份图解算法进阶指南,成功拿下字节offer

Geek_0c76c3

Java 数据库 开源 程序员 架构

数据中台建设5大关键步骤

阿泽🧸

数据中台 10月月更

OpenKruise v1.3:新增自定义 Pod Probe 探针能力与大规模集群性能显著提升

阿里巴巴云原生

阿里云 云原生 OpenKruise

大型企业选择低代码的主要原因是什么?

优秀

低代码 低代码平台

vue组件通信方式有哪些?

bb_xiaxia1998

Vue

见大牛、聊感悟、拿好礼...开发者一起来微软Ignite赴约!

InfoQ写作社区官方

热门活动

学了阿里大佬的 SpringCloud微服务项目真香!即刻涨薪35K

Geek_0c76c3

Java 开源 程序员 架构 面试

2022全网独一份Java面试题整理,包含30个技术栈, 1575 道Java 架构师面试题

Geek_0c76c3

Java 数据库 开源 程序员 开发

在数字化浪潮中,为企业建造一艘“方舟”

元年技术洞察

微服务 云原生 企业数字化 PaaS 平台

短期内跳槽的Java程序员必看的八项知识点+两大项目实战

Geek_0c76c3

Java 数据库 开源 程序员 开发

阿里资深架构师把大厂高频 2000+ 道 Java 面试题全部总结出来了,分分钟拿捏面试官

Geek_0c76c3

Java 数据库 开源 程序员 开发

【高并发】ScheduledThreadPoolExecutor与Timer的区别和简单示例

冰河

并发编程 多线程 高并发 协程 异步编程

进击的PyTorch,和它背后的开源领袖

OneFlow

人工智能 机器学习 深度学习 开源

Koordinator v0.7: 为任务调度领域注入新活力

阿里巴巴云原生

阿里云 云原生 Koordinator

Java:锁定 Excel 中的特定单元格

Geek_249eec

Java Excel 单元格

踩坑总结:鹅厂小哥教你注册中心宕机后正确的处理姿势_语言 & 开发_腾讯云中间件_InfoQ精选文章