避免大规模故障的微服务架构设计之道

作者:Péter Márton 
译者:Jackyrong


本文首先介绍微服务架构存在的风险,然后针对如何避免微服务架构的故障,提出了多种有效的微服务架构中的方法和技术,其中例如服务降级、变更管理、健康检查和修复、断路器、限流器等。

微服务架构通过定义明确的服务边界,能有效地隔离故障。 和其他分布式系统一样,微服务在网络、硬件和应用层上都会存在更多的问题。由于服务之间是互相依赖,因此任何组件都可能出错导致用户不能访问。为尽可能减少部分中断带来的影响,我们需要构建容错能力强的服务,以从容应对发生的某些中断。

本文在RisingStack’s Node.js Consulting & Development experience一文基础上,介绍了构建和运维高可用的微服务架构系统中最常用的技术和架构模式。

如果读者不熟悉上文中的模式,那并没什么大碍。构建可靠的系统不是一踞而就的。

微服务架构的风险


微服务架构将应用逻辑拆分成服务,服务之间通过网络交互。由于是通过网络调用,而不是在进程中调用,因此这给需要在多个物理和逻辑组件间进行协作的系统带来了潜在的问题和复杂性。分布式系统变得越来越复杂,也导致网络特定故障发生的可能性增大。 
   
相比传统应用庞大的结构,微服务架构最大的一个优点是团队能独立地设计、开发和部署各自的服务。团队能掌控各自服务的整个生命周期。这也意味者团队无法控制服务的依赖关系,因为这些依赖的服务可能是由其他团队管理。在微服务架构体系下,我们要牢记提供的服务由于是其他人控制,因此可能会由于发布、配置、和其他变更等原因,从而导致服务暂时不可用,而且组件之间互相独立。 

优雅的服务降级


微服务架构最大的优点之一就是当组件出现故障时,能隔离这些故障并且能做到优雅地服务降级。比如,在图片分享应用中,当出现故障时,用户可能无法上传图片,但他们依然能浏览、编辑和分享已上传的图片。 

微服务故障独立(理论上)

在大多数情况下,是很难实现上图这种优雅地服务降级的,因为在分布式环境下,应用都是互相依赖的,开发者需要实现若干错误处理的逻辑(该部分在本文稍后部分讨论)去应对短暂的故障和中断。

 

      服务互相依赖,如果无故障转移的逻辑,则会同时失效

变更管理


Google的网站可靠性团队发现大概70%的故障都是由于变更而引起的。当对服务进行修改时—例如发布代码的新版本或者改变一些配置,则总会有可能引起故障或者引入新的错误。

在微服务架构中,服务是互相依赖的。这就是为什么你需要减少故障并且尽可能降低它们的负面影响。为了应对变更带来的问题,你可以实施变更策略管理并且实现其自动回滚。

比如,当部署新的代码或者修改配置时,应该分步将这些变更部署到服务实例群中的部分实例中,并且进行监控,如果发现关键指标出现问题则能自动进行回滚。

变更管理-回滚部署

另一个解决方案是运行两套生产环境。部署的时候只部署变更的应用到其中一套环境中,并且在验证了新发布的版本符合预期后,才将负责均衡的流量指向新的应用,这种方法称为“蓝-绿发布”或者“红-黑发布”。

回退代码并不是坏事情。你不应该在生产环境中部署有问题的代码,并且应该琢磨哪里出错了。当必要时候应该果断回退代码,这越早越好。

健康检查和负载均衡


因为故障或部署、自动扩展等原因,服务实例会不停启动,重新启动及停止。这使得服务暂时或一直停用。为了避免发生这些问题,在负载均衡中应该在路由中设置忽略这些实例,因为它们无法为子系统或用户提供服务。 
   

我们可以通过外部观察去判断应用实例是否健康。你可以多次调用 
Get /health的端点(endpoint)或者通过自身服务的报告获得相关信息。现在的 
服务发现解决方案会持续从实例中收集健康信息,并且设置负载均衡的路由,让其只指向健康的实例组件。

自我修复


自我修复能帮助恢复应用。我们讨论下当应用遇到崩溃状态后,如何通过相关的步骤去自我修复。在大多数情况下,是通过外部系统监控实例的状态,当服务出现故障一段时间后则会重启服务。在大多数情况下,自我修复的功能是相当有用的,然而,在某些情况下由于不断地重启服务会带来相关的问题。例如当服务过载或者数据库连接超时,则会导致应用不能反馈正确的服务健康状态。

对于一些场景-比如数据库链接丢失,这个时候实现高级的自我修复功能是颇为棘手的。在这种情况下,需要为应用添加额外的逻辑去处理这些特例,并且让外部系统知道服务的实例不需要立即重新启动。

故障转移缓存(Failover Caching)


因为网络问题和系统中的变更,服务通常会出现故障。然而,这些故障中断大多是暂时的,这要归功于自我修复和高级负载平衡的功能,我们应该找到一个解决方案,能使服务即使在出现故障的时候也能工作。这就是故障转移缓存(Failover Caching),它能帮助为我们的应用提供必需的数据。

失效转移缓存通常使用两个不同的过期日期:其中更短的日期指示在正常情况下能使用缓存的时间,而更长的一个日期则指示在故障失效的时候,能使用缓存中的数据时长。

故障转移缓存

特别需要提醒的是,只有当提供过时的数据比没有数据更好的情况下,才能使用故障转移缓存。

要设置缓存和故障转移缓存,可以在HTTP中使用标准响应头。

例如,使用max-age头可以指定某个资源为新资源的最大时间(译者注:意即设定max-age后,浏览器不再发送请求到服务器)。可以使用stale-if-error 头去确定在出现故障的情况下,从缓存获取资源的时间长短。

现在的CDN和负载均衡器提供了各种缓存和故障转移的解决方案,但是你也可以在你的公司中建立一个共享库,其中包括这些标准的可靠性解决方案。

重试逻辑(Retry Logic)


在某些情况下,我们可能无法缓存数据,或者想对数据进行变更,但是操作最终失败了。在这种情况下,我们就可以选择重试操作,因为我们可以预期资源将在一段时间后恢复,或者负载均衡会将请求发送到健康的实例上。

你应该小心地为应用程序和客户端添加重试逻辑,因为更大量的重试操作可能会使事情变得更糟,甚至阻止应用程序恢复。

在分布式系统中,微服务系统重试可能会触发多个其他请求或重试操作,并导致级联效应。为减少重试带来的影响,你应该减少重试的数量,并使用指数退避算法(exponential backoff algorithm)来持续增加重试之间的延迟时间,直到达到最大限制。

由于重试是由客户端(浏览器,其他微服务等)发起的,并且客户端在处理请求前后是不知道草走失败的,你应该为你的应用程序提供幂等处理能力。例如,当你重试购买操作时,不应该向客户收两次钱。给每个事务使用唯一的幂等键(idempotency-key)是解决重试问题的方法。

限流器和负载开关(Rate Limiters and Load Shedders)


限流是指在一段时间内,定义某个客户或应用可以接收或处理多少个请求的技术。例如,通过限流,你可以过滤掉产生流量峰值的客户和微服务,或者可以确保你的应用程序在自动扩展(Auto Scaling)失效前都不会出现过载的情况。

你还可以阻止较低优先级的流量,以便为关键事务提供足够的资源。 

            限流器可以阻止流量峰值

另外有一种限流器,称为 “并发请求限流器(concurrent request limiter)”。当你有一些比较昂贵和重要的端点(endpoint),希望它不应该被调用超过指定的次数,但仍然想要提供流量服务时,这个限流器就十分有用了。

使用负载开关可以确保对于关键的事务总能提供足够的资源保障。它为高优先级的请求保留一些资源,并且不允许低优先级的事务去占用这些资源。负载开关会根据系统的整体状态做出决定,而不是基于单个用户的请求桶(request bucket)大小。负载设备有助于你的系统恢复,因为它们在持续发生故障事件时,依然能保持核心功能正常工作。

关于更多限流器和负载开关的知识,建议读者参考Stripe的相关文章。

快速且单独失效(Fail Fast and Independently)


在微服务体系架构中,我们希望服务可以快速、单独地失效。为了在服务层面隔离故障,我们可以使用隔板模式(bulkhead pattern)。可以在本文稍后看到相关介绍。

我们也希望我们的组件能够快速失效(fail fast),因为我们不希望等到断开的实例直到超时。没有什么比挂起的请求和无响应的界面更令人失望。这不仅浪费资源,而且还会让用户体验变得更差。我们的服务是互相调用的,所以在这些延迟叠加前,应该特别注意防止那些超时的操作。

你想到的第一个办法,可能是对每个服务的调用都定义超时的级别。这种做法的问题是,你不能真正知道到底什么是恰当的超时值,因为当网络故障和其他问题发生时,某些情况下只会影响一两次操作。在这种情况下,如果只有其中一些发生超时,你可能不想拒绝所有这些请求。

我们可以说,通过使用超时(timeout)来实现微服务中的快速失败是一种反模式,这是应该避免的。可以使用基于操作的成功/失败统计次数的熔断模式,而不是使用超时。

舱壁模式(Bulkheads)


在工业领域中,常使用舱壁将划分为几个部分,以便在有某部分船体发生破裂时,其他部分依然能密封安然无恙。

舱壁的概念也可以在软件开发中用于隔离资源。

通过使用舱壁模式,我们可以保护有限的资源不被用尽。例如,如果我们有两种类型的操作的话,它们都是和同一个数据库实例进行通信,并且数据据库限制连接数,这时我们可以使用两个连接池而不是使用一个共享的连接池。由于这种客户端和资源分离,超时或过度使用池的操作不会令所有其他操作失效。

泰坦尼克号沉没的主要原因之一是其舱壁设计失败,水可以通过上面的甲板倒在舱壁的顶部,最后整个船淹没。

             泰坦尼克号故障的舱壁

断路器(Circuit Breakers)


为了限制操作的持续时间,我们可以使用超时。超时可以防止挂起操作并保证系统可以响应。然而,在微服务架构通信中使用静态、微调的超时是一种反模式,因为我们处于高度动态的环境中,几乎不可能确定在每种情况下都能正常工作的准确的时间限制。

我们可以使用断路器来处理错误,而不是使用小型和特定基于事务的静态超时机制。断路器以现实世界的电子元件命名,因为它们的行为是都是相同的。你可以保护资源,并通过使用断路器协助它们进行恢。断路器在分布式系统中非常有用,因为重复的故障可能会导致雪球效应,并使整个系统崩溃。

当在短时间内多次发生指定类型的错误,断路器会开启。开启的断路器可以拒绝接下来更多的请求 – 就像防止真实的电子流动一样。断路器通常在一定时间后关闭,以便为底层服务提供足够的空间来恢复。

请记住,并不是所有的错误都应该触发断路器。例如,你可能希望忽略客户端问题,比如4xx响应代码的请求,但要包括5xx服务器端故障。一些断路器还可以有半开关状态。在这种状态下,服务发送第一个请求以检查系统的可用性,同时让其他请求失败。如果这个第一个请求成功,则将断路器恢复到关闭状态并继续接受流量。否则,保持打开状态。

断路器

故障测试(Testing for Failures)


你应该持续地测试系统的常见问题,以确保你的服务可各类故障环境下运行。你应经常测试故障,以让你的团队对可能发生的事故有所准备。

关于测试,你可以使用外部服务来识别服务实例组,并随机终止运行组中的一个实例。通过使用这个方法,可以针对单个实例故障进行测试,你甚至可以关闭整个服务组来模拟云提供商层面的故障中断。

最流行的测试解决方案之一是Netflix的ChaosMonkey工具。

总结


实施和运维可靠的服务并不容易。这需要你付出很多努力,还要花费公司更多的成本。

可靠性有很多层次和方面,因此针对你的团队找出合适的解决方案是相当重要的。你应该将可靠性成为业务决策流程中的一个因素,并为此分配足够的预算和时间。

要点

  • 动态环境和分布式系统-如微服务将导致更高的故障机会。

  • 服务应单独失效,实现优雅的服务降级以提升用户体验。

  • 70%的问题是由变更引起的,恢复可用代码并不总是坏事。

  • 快速,单独地失败。团队无法控制其服务依赖关系。

  • 架构模式和技术,如缓存、隔离技术、断路器和限流器有助于构建可靠的微服务。


读者可以通过阅读我们免费的电子书Node.js Monitoring, Alerting & Reliability 101 e-book以学习可靠的微服务

作者简介:


Péter Márton,是RisingStack的CTO , 擅长使用nodejs来构建微服务。他的twitter帐号为 
https://twitter.com/slashdotpeter


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/525827.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI 线上峰会 | 人工智能技术解析与实战

10月28日, SDCC 2017“人工智能技术实战线上峰会”将在CSDN学院以直播互动的方式举行。 如今人工智能已不单单是发表学术论文、刷新正确率的竞赛,抑或全民参与的新闻事件,它早在为各行各业的先行者们创造着实实在在的利润和商业价值。而且&am…

五阿哥钢铁电商资深运维工程师手把手教你这样玩企业组网

虽说干的是信息化智能化的行当,但每个IT工程师都必定踩过“IT系统不智能”的坑。就拿企业组建局域网来说,为了对网络接入用户身份进行确认,确保用户权限不受办公地点变更的影响,许多IT工程师都习惯开启 “手动模式”和苦逼的“加班…

预告:Intel、Hulu、阿里、京东、携程等大数据实战直播

前言:由CSDN主办的SDCC 2017之大数据技术实战线上峰会将在CSDN学院举行。作为SD系列技术峰会的一部分,本次线上峰会秉承干货实料(案例)的内容原则,将邀请圈内顶尖的布道师、技术专家和技术引领者,共话大数据…

微服务应用容器化场景中常见问题总结

简介:云原生技术栈是下一代应用转型的必然选择,它包含了微服务架构,DevOps和容器技术。对于微服务架构来说,应用是“第一公民”,他逐渐蚕食原来底层软件或者硬件的功能,例如服务注册与发现以及负载均衡&…

Swarm的进化和大规模应用

目前在容器编排领域,Kubernetes、Mesos以及Swarm呈现“三分天下”的格局,各自都有着不同的应用场景。短期内,很难看到“一统天下”的局面,本文,来自阿里云高级专家陈萌辉将带你了解阿里内部在推行容器化过程中的一些着…

linux可以用dos命令是什么意思,Linux系统常用命令与DOS命令的类似之处和本质区别各是什么?...

满意答案iedsa3641推荐于 2019.09.13采纳率:56% 等级:8已帮助:361人Linux是一个非常优秀的操作系统,与MS-WINDOWS相比具有可靠、稳定、速度快等优点,且拥有丰富的根据UNIX版本改进的强大功能。下面做一个…

从 0 到 300,Instagram 创始人 CTO 分享工程团队成长的经验

最初,Instagram 被 Facebook 收购时公司只有六个工程师,且都是全栈。本文Instagram 创始人兼 CTO Mike Krieger 分享了创业初期并在资源有限的情况下,人才招聘、技术专攻的实践经验,将时间、精力用在最有价值的地方。以下为译文&a…

深度揭秘Twitter的新一代流处理引擎Heron

流计算又称实时计算,是继以Map-Reduce为代表的批处理之后的又一重要计算模型。随着互联网业务的发展以及数据规模的持续扩大,传统的批处理计算难以有效地对数据进行快速低延迟处理并返回结果。由于数据几乎处于不断增长的状态中,及时处理计算…

linux生成图片快捷方式,在Deepin Linux系统下给AppImage格式软件创建快捷方式的方法...

这两天使用deepin的过程中,无意中发现了一个叫krita的程序,是一个图像处理软件,类似Photoshop,于是就下载krita-4.2.8-x86_64的这个版本。但是麻烦的就是他是一个AppImage格式,每次我打开的时候需要打开相应文件夹中的…

图数据库在CMDB领域的应用

【导语】在上期的图数据库介绍中,我们对什么是图数据库,以及图数据库所擅长的领域做了一个初步的介绍,也收到了众多的反馈和咨询,特别要求我们对图数据库在一些具体行业的应用能做一些深入介绍。为此,从本期文档开始&a…

从分布式到微服务,深挖Service Mesh

原文:Pattern: Service Mesh (作者/Phil Calado,翻译/雁惊寒,责编/魏伟 ) 摘要:在前一段时间,我们CSDN推出了《深度剖析Service Mesh服务网格新生代Istio》一…

c语言程序设计课件数组,数组(C语言程序设计)课件

数组(C语言程序设计)课件 前牙反颌和开颌的原因多由于不良喂养方式和吮指等不良习惯造成,也可因多颗乳磨牙过早缺失,迫使儿童用前牙咀嚼,下颌逐渐前伸移位造成。 前牙反颌和开颌的原因多由于不良喂养方式和吮指等不良习惯造成,也可…

Docker CE/EE 原生支持Kubernetes

在今天的 DockerCon EU (2017) 上,Solomon 宣布 Docker 将原生支持 Kubernetes,也就是说 Kubernetes 将和 Swarm 一样作为 Docker 平台的编排管理系统。这包括 Docker EE、Docker CE 以及 Docker for Mac/Windows 等全平台的支持。 Docker for Mac/Windo…

网易云容器服务基于Kubernetes的实践探索

Kubernetes的特点 近年来Docker容器作为一种轻量级虚拟化技术革新了整个IT领域软件开发部署流程,如何高效自动管理容器和相关的计算、存储等资源,将容器技术真正落地上线,则需要一套强大容器编排服务,当前大红大紫的Kubernetes已经…

c语言程序设计中三子棋游戏,C语言实现简易版三子棋游戏

本文实例为大家共享了C语言实现三子棋游戏的详细代码,供大家参考,详细内容如下什么是多文件?多数大型的工程的头文件和源文件非常多,我们也不可能把所有的代码都写在同一个文件里,这样也不方便代码的阅读与维护&#x…

Rancher创始人谈Docker,创新愈发困难,未来将何去何从?

导读:本文由Rancher Labs CEO及联合创始人梁胜博士在参加DockerCon之前和之后写的两篇文章综合整理而成。从各家容器编排方案均很不成熟的初期到三足鼎立的编排之战,到如今kubernetes似已全面胜利,梁胜博士作为整个发展历程的参与者与见证者,…

ld 指令c语言实现,C语言符号、指令表.doc

C语言符号、指令表.docC语语语 言言言 符符符 号号号 控控控 制制制 命命命 令令令 表表表 编译指令 编译指令 说明 i n c l u d e 包含另一个文件 d e f i n e 定义一个宏( m a c r o)或是常量 u n d e f 取消一个宏常量的定义 a s m 和 e n d a s m 在程序中加入汇编语言的程…

400位京东技术专家心血之作 《决战618:探秘京东技术取胜之道》重磅发售!

6.18始于京东的店庆日,现在早已演变成为全民参与的网购狂欢节。2017年6月18日24点,当京东总部的指挥中心大屏定格在“当前累计下单金额1199亿元”时,欢呼声、掌声响彻整个作战指挥室。在成绩背后,是京东强大的技术硬实力&#xff…

c语言创建一个顺序表主函数,用C语言来创建一个顺序表(数据结构部分)

顺序表的创建需要用到结构体,构造一个结构体来存储数据,顺序表申请的内存是连续的。创建顺序表的思路按照数据的“增删改查来进行编写”下列是顺序表的创建代码创建头文件:sqlist.h#ifndef SQLIST_H#define SQLIST_H#define N 100#define min…

XSS常见攻击与防御

本文获得作者授权刊发,更多信息请关注作者专栏。 XSS攻击全称跨站脚本攻击,是为不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS,XSS是一种在web应用中的计算机安全漏洞,它允许恶意…