发布-设计与部署稳定的分布式系统

读书摘要 --  第四章

高度交互的复杂性和紧耦合这两个“幽灵”,会将快速动态变化的裂纹转变为彻底的系统事故。

本章将讨论会破坏系统的反模式。这些是造成多种系统失效的常见原因。每一个反模式都会在系统中产生、加速或增加裂纹。应该避免这些不良的行为。

4.1 集成点

项目的上下文关系图无非是下面两种:蝴蝶图或蜘蛛图。

蝴蝶图:有一个中央系统,其中一侧有大量传入和连接的扇入数据,另一侧则有大量扇出数据;

蜘蛛图:图中有很多方块和相互的依赖关系。精心设计的是分层图;随意设计的则是MESH蜘蛛网;

这几种风格的共同特点是连接数超过服务数。蝴蝶图有2N个连接数,而蜘蛛网最多会有N*N个连接数,大部分系统的连接数则介于两者之间。

所有这些连接都是集成点,集成点是系统的头号杀手。每一个传入的连接都存在稳定性风险。每个套接字、进程、管道或RPC都可能停止响应。

例如:套接字

网络系统失效按速度分为快慢两种。快速的网络系统失效,会让调用代码立即出现异常。“拒绝连接”是非常快速的系统失效,只需要几毫秒的时间就能返回给调用方。缓慢的系统失效,比如一个被丢弃的ACK,会让线程在抛出异常之前被阻塞几分钟。被阻塞的线程无法处理其他事务,因此系统的容量就会降低。如果所有线程最终都被阻塞,那么实际上服务器就已被关闭了。显然,一个缓慢的响应比没有响应糟糕得多。

套接字连接是一个抽象概念,只有在计算机终端内存中,它们的存在才有意义。一旦创建套接字,TCP连接就可以保持好几天,而且无须任何一方发送数据包。只要两个终端计算机内存中都具有该套接字状态,那么“连接”就仍然有效。路由可以改变,物理链路可以被断开和重新连接,这些都没关系,只要终端的两台计算机认为“连接”确实存在,那么“连接”就会持续存在。

而网络中间的防火墙内的“已建立连接”表。该表是有时长限制的。因此,即使TCP本身允许无限时长的连接,该表也不允许。解决方案:周期的ping报。

要点:

小心必然会出现的恶魔。每个集成点最终都会以某种方式发生系统失效,所以需要为系统失效做好准备。

为各种形式的系统失效做好准备。集成点的系统失效有多种形式,如各种网络错误和语义错误。通过明确的协议获得良好的错误响应是不现实的,相反,某种协议违规、缓慢响应或停止响应等,这些情况更为常见。

知道何时应该揭开抽象。调试集成点的系统失效,通常需要透过抽象看问题。由于系统失效大多违反了高层协议,因此往往很难在应用层调试。此时可以求助于数据包嗅探器和其他网络诊断工具。

系统失效会迅速蔓延。若系统代码缺乏一定的防御性,那么远程系统失效会以层叠失效的方式迅速演变为系统问题。

采用一些模式来避免集成点问题。利用断路器、超时、中间件解耦和握手等模式进行防御性编程,以防止集成点出现问题。

4.2 同层连累反应

水平扩展通过增加服务器来增加容量;

垂直扩展,即构建越来越大的服务器,为主机添加CPU核数、内存和存储空间;

部分交互式工作负载通过垂直扩展实现,大多数交互式工作负载则依赖水平扩展;

尽管集群水平扩展不易遭遇单点系统失效,但它们可能会出现与负载相关的系统失效。

如果由于某些和负载相关的原因(例如内存泄漏或间歇性竞态条件),导致第一台服务器无法工作,那么幸存的节点会更容易发生系统失效。

如果应用程序存在缺陷(通常是资源泄漏或与负载相关的崩溃),就会发生同层连累反应。某一层上同层连累反应的系统失效容易导致其调用层上的层叠失效。

要点:

记住:一台服务器的停机会波及其余服务器。由于一台服务器停机,其他服务器必须负担其工作负载,这样就会发生同层连累反应。增加的负载使得剩余的服务器更易发生系统失效。同层连累反应会迅速让整层系统停机。依赖该层系统的其他层级必须做好防护措施,否则将会陷入层叠失效。

寻找资源泄漏。大多数情况下,如果应用程序发生内存泄漏,便会发生同层连累反应。当一台服务器耗尽内存并停机时,其他服务器不得不负担它的工作负载,但所增加的流量会加快内存泄漏。

寻找难以捕捉的时序缺陷。流量状况也可能引发难以捕捉的竞态条件。同样,如果一台服务器陷入死锁,其他服务器所增加的负载也极易使它们陷入死锁。

采用自动扩展。应该为云端的每个自动扩展组创建健康状况检查机制。自动扩展将关闭未通过健康状况检查的服务器实例,并启动新的实例。只要自动扩展机制的响应速度比同层连累反应的蔓延速度快,那么系统服务就依然可用。

利用“舱壁模式”进行保护。使用舱壁模式分隔服务器,可以防止同层连累反应毁掉整个系统服务。但当被分隔的服务器停机时,它们无法帮助其调用方确定哪个服务器分隔区停止了工作,不过这时调用方可以使用断路器模式。

4.3 层叠失效

当某一层系统崩溃导致其调用层也发生裂纹时,就发生了层叠失效。

层叠失效通常源于枯竭的资源池。资源池枯竭的原因往往是较低层级所发生的系统失效。没有设置超时时间的集成点,必定会导致层叠失效。

推测性重试也会让系统失效“跳过层级之间的间隙”而蔓延。服务提供方的响应变慢,调用方发出更多推测性重试请求,在服务提供方已经放慢响应时,占用调用方更多的线程。

要点:

阻止裂纹跨层蔓延。当裂纹从一个系统或层级跳到另一个系统或层级时,会发生层叠失效。这通常是因为集成点没有完善自我防护措施。较低层级中的同层连累反应也可能引发层叠失效。一个系统肯定需要调用其他系统,但当后者失效时,需要确保前者能够保持运转。

仔细检查资源池。层叠失效通常是由枯竭的资源池(例如连接池)所导致的。当任何资源调用都没有响应时,资源就会耗尽。此时获得连接的线程会永远阻塞,其他所有等待连接的线程也被阻塞。安全的资源池,总是会限制线程等待资源检出的时间。

用超时模式和断路器模式实现保护。层叠失效在其他系统已经出现故障之后发生。断路器模式通过避免向已经陷入困境的集成点发出调用请求,进而保护系统。使用超时模式,可以确保对有问题的集成点的调用能及时返回。

待补充

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容