当微服务发生故障后怎么办?来源于《微服务设计》

当微服务失败时会发生什么?最近发生在线故障。一个界面查询慢拖累了整个应用,导致整个应用不可用。如果正好赶上流量高峰,重启应用就变得非常困难,除非关闭整个入口,然后重启应用等待应用恢复。

在审查的时候,结论是增加上线审查流程和控制,以尽量防止故障再次发生,并没有考虑如何更容易地从故障中恢复.

我在这次停电期间也做了一些思考,如果我当时正在处理停电,我能做些什么?因此,本文开始,部分借鉴了上一家公司做稳定性建设的经验,部分借鉴了《微服务设计》中写的经验。分为前技术思维和可以做的技术事情。

技术实施前的思考

想想一、假设会发生故障,如何优雅地处理它。

假设一切都会失败,这会让你对如何解决问题有不同的想法。我们可以花更少的时间试图防止不可避免的失败,而花更多的时间优雅地处理它。假设失败会发生,如果你以这种心态处理你所做的一切并为失败做好准备,那么就会有不同的权衡。

了解您可以容忍多少故障,或者系统需要多快,以及系统用户的负载能力。

思考二、系统的强依赖和弱依赖

查看系统下游接口的强度,哪些接口强依赖哪些弱依赖。强依赖一般说明这个服务有问题,进程会卡住,直接影响功能,否则就是弱依赖。要有强弱依赖梳理工具,可以查询接口的调用链,根据业务场景判断哪些接口是强依赖,哪些是弱依赖。

强弱依赖的接口治理:首先去除不必要和不合理的依赖;所有不影响核心业务的依赖都变成弱依赖;弱依赖:增加降级开关,紧急情况下直接降级;配置限流;强依赖:缓存可以加入缓存;添加计划开关,可以快速止血。

想想三、业务中哪些功能可以降级

构建一个有弹性的系统,尤其是当功能分布在多个可能失败的不同微服务中时,对于能够安全地降低功能非常重要。我们需要做的是了解每个故障的影响,并弄清楚如何适当地降低功能。如果购物车服务不可用,我们可能会很麻烦,仍然可以显示列表列表页面。也许只是隐藏购物车并将其替换为新图标“即将回来!”。如果下单的红包服务不可用,用户降级后仍可正常下单。对于每个使用多个微服务的面向用户的界面,或者每个依赖多个下游合作伙伴的微服务,您需要问自己:“如果这个微服务出现故障会发生什么?”知道要做什么。通过考虑每个跨职能需求的重要性,我们可以更好地定位我们可以做什么。现在,让我们考虑在技术上可以做些什么来确保优雅地处理故障。

两个可以做的技术性事情

在分布式架构中,准备好应对各种故障非常重要。那么我们需要做些什么来处理系统故障呢?

1.超时设置

超时很容易被忽略,但在使用下游系统时正确处理它很重要。在考虑下游系统确实关闭之前,我必须等待多长时间?如果你等太久才决定调用失败,整个系统就会变慢。如果超时太短,您可能会将可能仍在工作的调用误认为失败。如果根本没有超时,下游系统可能会挂起整个系统。为所有跨进程调用设置超时并选择默认超时。发生超时时,记录日志以查看发生了什么,并相应地进行调整。

2.断路器

即使我们正确设置了超时时间,也需要很长时间才能得到错误。然后我们会在下一个请求进来的时候再试一次,同样的等待。下游服务的故障会降低我们整个系统的速度。

使用熔断器时,当对下游资源的请求达到一定数量失败时,熔断器会打开。接下来,所有请求都会在断路器打开的情况下快速失败。一段时间后,客户端发送一些请求,看看下游服务是否恢复,如果得到正常响应,就会重置断路器。

断路器概述(图片来自《微服务设计》)

如何实现断路器取决于请求失败的定义,但是当使用 HTTP 连接实现它们时,我会将超时或 5XX 的 HTTP 返回代码视为失败的请求。这样,当下游资源宕机、超时、返回错误码时,达到一定阈值后,我们会自动停止向它发送通信,并开始快速失败。当它恢复健康时,我们会自动重新发送请求。

正确设置断路器可能有点棘手。您不想太容易激活断路器,也不想花费太多时间来激活它。同样,您要确保在下游服务真正健康之前不发送通信。与超时一样,我选择了一些合理的默认值并在所有地方使用它们,然后在特定情况下进行调整。

当断路器打开时,您有几个选择。其中之一是堆积请求,然后稍后重试。对于某些情况,这可能是合适的,特别是如果您正在做的工作是异步工作的一部分。但是,如果调用是作为同步调用链的一部分进行的,fail-fast 可能更合适。这意味着,在调用链上传播错误,或降级功能。

如果我们有这样的机制(例如我们家中的断路器),我们可以手动使用它们来使我们所做的工作更加安全。例如,如果作为日常维护的一部分,我们想要停用一个微服务,我们可以手动为所有依赖它的系统启动断路器,如果这个微服务失败,它们就会快速失败。微服务恢复后,我们可以重置断路器,让一切恢复正常。这里的机制在电子商务中经常使用,就是使用开关来降级所依赖的功能。比如大促期间,为了应对流量高峰,关闭部分功能。

3.隔板模式

隔板是一种将自己与失败隔离开来的方式。在航运中,舱壁是船舶的一部分,在关闭时可保护船舶的其余部分。因此,如果甲板被穿透,您可以关闭舱壁门。如果船的一部分丢失了,但其余部分仍然完好无损。

在软件架构方面,需要考虑许多不同的隔板。

(1)为每个下游服务连接使用不同的连接池

我们应该为每个下游服务连接使用不同的连接池。这样,如果一个连接池耗尽,其余连接不受影响。这样可以保证以后下游服务慢的时候,只有一个连接池会受到影响,其他调用仍然可以正常进行。

(2)应用拆分

关注点分离也是实现隔板的一种方式。通过将功能分离为独立的微服务应用程序,可以减少一个功能关闭而另一个功能受到影响的可能性。这里我们可以按功能进行拆分,也可以根据应用是否为核心来拆分核心应用和非核心应用。

(3)使用断路器

我们可以将断路器视为一种自动机制,它密封了一个隔板,不仅可以保护消费者免受下游服务问题的影响,还可以防止下游服务进行更多调用以防止可能的不利影响影响。考虑到级联故障的危险,我建议对所有同步下游调用使用断路器。当然,没有必要重新创建自己的断路器。 Netflix 的 Hystrix library() 是一个基于 JVM 的断路器,具有强大的监控功能。

在许多方面,舱壁是三种模式中最重要的一种。超时和断路器可以帮助您在资源受限时释放它们,但隔板可以确保它们不会首先成为约束。例如,Hystrix 允许您实现在某些条件下拒绝请求的隔板,以避免资源饱和,这称为减载。有时拒绝请求是避免关键系统不堪重负或成为多个上游服务瓶颈的最佳方法。

4.隔离

一项服务对另一项服务的依赖程度越高,另一项服务的健康状况就越会影响其正常运行的能力。如果我们使用允许下游服务器离线的集成技术,上游服务就不太可能受到计划内或计划外停机的影响。

增强服务之间的隔离还有另一个好处。当服务彼此隔离时,服务所有者之间需要较少的协调。团队之间的协调越少,这些团队的自主性就越高,因此他们可以更自由地管理和发展服务。

这些都是在故障发生之前需要在技术上做好准备的事情。如果在故障发生之前什么都不做,看来重启应用的唯一方法就是希望下游接口能够快速恢复这条路径。如果赶上流量高峰,恐怕连入口都需要关闭,申请才能上来。因此,需要提前做好架构保护措施,并确保如果出现问题,它们不会造成严重的级联效应。在系统中将它们标准化,以确保一项服务的单个问题不会导致整个系统瘫痪。

© 版权声明
THE END
喜欢就支持一下吧
点赞38 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片