想提升微服务容错性?试试这5种模式

作者 |  Igor Perikov

译者 | 陆离

责编 | 徐威龙

出品 | CSDN云计算(ID:CSDNcloud) 

 

在本文中,我将介绍微服务中的几种容错机制及其实现的方法。如果你在维基百科上查找“容错性”,你将会发现有如下的定义:

 

“容错性是一种特性,它使系统能够在某些组件发生错误时仍能继续正常地运行。”

 

对于我们来说,一个组件意味着很多:微服务、数据库(DB)、负载均衡器(LB),你可以给它命个名。我在这里不讨论数据库和负载均衡器的容错机制,因为它们是特定于供应商的,并且如果使用它们的话,需要设置一些属性或者更改部署策略。

 

作为一个软件工程师,应用程序是我们展现自身力量和承担责任的地方。下面,我将从以下几个方面进行介绍容错性:

  • 超时(Timeouts)

  • 重试(Retries)

  • 熔断机制(Circuit Breaker)

  • 截止时间(Deadlines)

  • 限流器(Rate limiters)

有些模式是广为人知的,你甚至可能都会觉得有些不值得一提,但也请紧跟本文的思路,我将要简要介绍这几个基本的容错方法,然后一一讨论它们的缺点以及应该如何避免。

超时

超时是指允许等待某个事件发生的指定时间范围。如果使用SO_TIMEOUT(也称为socket timeout或read timeout)参数则会出现问题,它表示任何两个连续数据包之间的超时,而不是整个请求的响应时间,因此很难满足SLA(Service-Level Agreement,服务等级协议),特别是在应用服务响应负载很大的情况下。通常来说,我们所说的超时,是覆盖了从建立请求连接到响应最后一个字节完成的整个交互过程。不过,它们不适合使用SO_TIMEOUT参数。想要在JVM中避免使用它,可以使用JDK11或是OkHttp客户端。Go语言在std库中也有一个相关的机制。

重试

如果你的请求失败了,那么请稍等一会儿,然后再试一次。重试的过程基本上就是这样的。重试是有意义的,因为网络可能会降级服务一段时间,或者GC(垃圾回收)会命中请求所到达的特定实例。现在,让我们来想象有如下所示的服务调用过程:

             

如果我们将每个服务的请求尝试次数上限设置为3,并且服务D突然发生完全中断的错误,那么会发生什么情况呢?这将导致一场请求重试风暴,当服务链中的每个服务开始重试它们的请求时,会由此大大增加了总负载量,所以服务B将面临担负是通常情况下3倍的请求负载,C是9倍,而D是27倍。冗余是实现高可用性的关键原则之一,但我怀疑在这种情况下,集群C和D上是否还有足够的空闲资源。将尝试次数上限设置为2也不会有多大帮助,而且它会使在较小blip上的用户体验会更糟。

 

解决方案:

  • 区分可重试错误和不可重试错误。当用户没有权限或负载结构不正确时,重试请求是没有意义的。相反,重试请求超时或返回代码5xx是没有问题的;

  • 设置错误重试机制。当重试错误次数超过阈值时停止重试,例如,与服务D进行交互,如果20%的结果都是错误的,则停止重试并尝试降级服务。在过去的N秒内,可以使用滚动窗口跟踪错误量;

熔断机制

熔断器可以作为一个更严格的错误率预置方案。当错误率过高的时候,任务将不会继续执行,如果提供了回退结果,那么就会返回。无论如何,首先应该选择先执行很少的一部分请求,以便了解目标服务是否已经恢复了。在人工干预之前,我们应该给目标服务一个自己恢复的机会。

 

你可能不太赞同上述的方法,如果一个功能处于关键路径上,启用熔断器是没有意义的,但不要忘了,这种短暂的、可控的“自动断电”可能会阻止一次大的、不可控的服务中断。

 

尽管熔断机制和错误重试机制有着相似的想法,但是它们在实际应用的过程中是非常有意义的。由于错误重试机制的破坏性较小,因此,其阈值尽量要设的低一些。

 

Hystrix是一个在JVM中的go-to模式熔断机制的实现。到目前为止,它已经进入了维护模式,建议使用resilience4j来替代。

截止时间/分布式超时

我们已经在本文的第一部分讨论了超时模式,现在让我们看看如何实现它们的“分布式”。首先,再一次访问相互调用的一系列服务链:

             

服务A最长可以等待400毫秒,并且一个请求需要依次调用3个下游服务才能完成任务。假设对服务B的请求和响应花了400毫秒,下一步就准备调用服务C。那么,这种情况是不合理的,一旦服务超时,就不应该再等待任何结果。如果继续下去只会浪费资源,增加请求重试风暴发生的风险。

 

为了实现这个过程,我们必须在请求中添加额外的元数据,这将有助于理解在什么时候进行中断处理是最合理的。理想情况下,这应该得到所有服务的支持,并在整个调用流程中进行参数的传递。

 

在实际的过程中,上述元数据可以分为以下几种形式:

  • Timestamp(时间戳):是通过服务停止等待响应的时间点。首先,网关或者前端服务将截止时间设置为“当前时间戳+超时”。接下来,任何下游服务都应该检查当前时间戳是否超过了截止时间。如果超过了,那么要停止响应,否则,就开始处理。遗憾的是,服务器之间的时间可能是不同的,存在着时钟偏差的问题。如果存在这种情况,那么,请求将会被阻塞或者立即被拒绝,从而导致服务停止;

  • Timeout(超时):传递允许服务等待的时间。这个问题有点棘手,和之前一样,你需要尽快设定截止时间。接下来,任何一个下游服务都应该对自身处理过程进行计时,并从设定的超时时间中减去这个时间,然后传递给下一个服务。重要的是不要忘记进入请求队列等待的时间。因此,如果服务A允许等待400毫秒,而调用服务B花费150毫秒,则在调用服务C时必须告知有250毫秒的超时时间限制。虽然它没有把传输时间也计算在内,但截止时间只能在之后而不是更早的时间触发,因此,这可能会消耗更多的资源,但不会影响结果。在GRPC(Google开发的高性能、通用的开源RPC框架)中的截止日期就是这样实现的。

 

最后我们要讨论的是,当超过了截止时间时,不去中断调用服务链是否有意义,答案是肯定的,如果你的服务有足够的处理资源,并且在完成请求之后会使其更活跃(缓存/JIT),那么让其继续处理就可以了。

限流器

前面讨论的模式主要解决了级联失效的问题,依赖服务在其依赖关系崩溃后也随之崩溃,最终导致整个服务完全宕掉的情况。现在,让我们来讨论一下当你的服务出现过载的情况。有很多技术方面的原因可能会导致服务过载,那么,现在我们就假设发生了这种情况。

 

每个应用程序都有其未知的处理极限。这个值是动态的,取决于多个变量,例如近期的代码更新、正在运行的CPU的模式、主机的繁忙程度等等。

 

当负载超过极限时会发生什么呢?通常,这种恶性循环会出现在如下的情况里:

1.  响应时间增加,GC占用空间增加;

2.  客户端出现了越来越多的处理超时,甚至承担了更多的负载量;

3.  比1的情况更严重;

 

这里有个例子。当然,如果客户端有错误重试机制或者熔断机制,第二种情况可能不会产生额外的负荷,从而会获得一个跳出的机会。其它的情况可能会发生,从负载均衡的上游列表中删除实例可能会在加载和剔除相邻实例等方面导致更多的不平衡。

 

对于限流器,它们的做法是优雅地拒绝新的请求,这就是理想情况下应该如何处理过度负载:

 

1.  限流器将额外的负载量降到可承受的范围以内,从而使应用程序能够根据SLA进行服务请求;

2.  过多的负载被重新分配到其它的实例,或者进行集群的自动/被动缩放;

 

有两种类型的限流器:速率和并发。前者用来限制允许的请求数量,后者用来限制在任何时刻同时处理的最大请求数量;

 

为了简便起见,假设对服务的所有请求在计算资源的消耗上是一致的,并且具有相同的权重。不同的用户会有不同数量的数据,例如喜欢的电视节目或者以前的订单等等。通常,采用分页技术有助于实现请求在计算资源消耗上的相等。

 

限流器使用的更广泛,但并不像并发限制那样能提供强大的保证,所以如果你希望选择一个的话,建议坚持使用并发限制机制,原因如下。

 

在配置限流器的时候,我们认为会强制执行如下的操作:

服务可以在任何时间点进行每秒N个请求的处理。

但实际上,我们想要说的是:

假设响应时间相同,那么在任何时间点服务都可以进行每秒N个请求的处理。

 

为什么这句话这么重要?我会用直觉来“证明”。而对于那些愿意用数学来证明的人,查一下什么是排队理论。

 

假设限流器设置为1000rps,响应时间为1000毫秒,SLA为1200毫秒。在给定的SLA的条件下,我们很容易算出,在1秒钟内服务能同时处理1000个请求。

 

现在,响应时间增加了50毫秒(依赖的服务开始处理额外的工作)。从现在起,由于请求数超过了处理能力,在每1秒服务都将面临同时需要处理越来越多的请求。如果线程的数量不受限制的增长,那么就意味着你的资源将会被一点一点的耗尽,并直至系统崩溃,尤其是在应用程序的线程1:1地对应到操作系统线程的时候。如何能处理1000个请求的并发限制呢?它可以服务于1000/1.05=~950个RPS,而不会违反SLA协议,然后放弃其余的请求。另外,还不需要重新进行配置。

 

我们可以在每次服务的依赖关系发生变化时更新流量限制,但这是一个巨大的工作量,可能需要在每次变化时对整个生态系统进行重新配置。

 

根据阈值的设置方式,它可以分为静态的和动态的。

静态的限流

在这种情况下,限制范围是通过手动进行配置的。阈值可以通过定期的性能测试来评估。然而它不可能是100%准确的,另外,对于安全性来说,可能也会有一定的影响。这种类型的限制要求围绕CI/CD(持续集成/持续交付)管道来进行工作,而且资源利用率也较低。静态的限流器可以通过限制工作线程池的大小(仅限并发)、添加可以计算请求数量的请求过滤器、以及NGINX limiting functionality或envoy sidecar proxy来实现。

动态的限流

在这里,限制取决于度量,度量是在规则的基础上重新计算的。很有可能的是服务过载与响应时间变长之间存在着相关性。如果是的话,度量可以是响应时间的统计函数,例如百分比、中等或平均值。还记得计算等式属性吗?这个属性是更精确计算的关键。

然后,定义一个术语用于表示度量是否正常。例如,p99≥500ms被认为是服务不正常,因此应降低限制范围。如何增大和减小限制范围应该由一个请求反馈控制算法来决定,如AIMD(Additive Increase Multiplicative Decrease,在TCP协议中使用)。下面是它的伪代码:

                           

如你所见,限制的范围增大缓慢,检测应用程序是否运行良好,如果发现错误行为则急剧减小。

 

Netflix开创了动态限制的思想,并且开源了解决方案,这里是代码库:https://github.com/Netflix/concurrency-limits。它实现了几种反馈算法、静态限流器的实现、GRPC集成和Java servlet集成。

 

就说到这里吧,希望你从本文里学到一些有帮助的内容。我想指出的是,上述所说的并不是尽善尽美的,你还应该具有良好的观察能力,因为在实际应用的过程中,可能会发生一些意想不到的问题,需要你能更好地了解当前应用程序的情况。不管怎么样,实现上述这些方法,将有助于解决你当前出现的或者是潜在的一些问题。

 

原文链接:

https://itnext.io/5-patterns-to-make-your-microservice-fault-tolerant-f3a1c73547b3

本文为CSDN翻译文章,转载请注明出处。

推荐阅读

  • 十年云计算大爆发,微软正在摧毁其它竞争对手

  • 小网站的容器化(上)

  • 盘点丨2019十大边缘计算项目我国自主开发的编程语言“木兰”是又一个披着“洋”皮的红芯浏览器吗?

  • 以太坊 2.0 前途光明!


真香,朕在看了!

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

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

相关文章

21世纪了还愚公移山?数据库这么迁移更稳定!

背景 在系统的快速迭代过程中,业务系统往往部署在同一个物理库,没有做核心数据和非核心数据的物理隔离。随着数据量的扩大这种情况会带来稳定性的风险,如库的慢sql,磁盘,IO等等都会相互整体影响,从而影响核…

Oracle 创建表空间、用户、权限_(plsql)

背景:企业内部oracle数据库日常oracle表空间、用户、权限操作 文章目录1. 使用dba用户登录plsql2. 创建表空间3. 创建用户4. 赋予用户权限5. 验证6. 完整脚本1. 使用dba用户登录plsql 2. 创建表空间 -- 创建表空间设置表空间大小 CREATE TABLESPACE fisknow DATAFI…

2019五个最棒的机器学习课程

凭借强大的统计学基础,机器学习正在成为最有趣,节奏最快的计算机科学领域之一,目前已经有无穷无尽的行业和应用正在使用机器学习使它们更高效和智能。 聊天机器人、垃圾邮件过滤、广告投放、搜索引擎和欺诈检测是机器学习模型正在实际应用于…

“天河二号”总工程师杜云飞谈星光超算应用平台设计

整理 | 夕颜出品 | AI科技大本营(ID:rgznai100)【导读】12 月 21-22 日,OpenI/O 启智开发者大会在深圳召开。在大会上, 国家超级计算广州中心总工程师、“天河二号”总工程师杜云飞发表了题为《星光超算应用平台》的主题报告&…

蚂蚁金服开源 SOFAJRaft:生产级 Java Raft 算法库

什么是 SOFAJRaft? SOFAJRaft 是一个基于 Raft 一致性算法的生产级高性能 Java 实现,支持 MULTI-RAFT-GROUP,适用于高负载低延迟的场景。 使用 SOFAJRaft 你可以专注于自己的业务领域,由 SOFAJRaft 负责处理所有与 Raft 相关的技…

如何在mysql查询结果集中得到记录行号_获取MySQL查询结果集中记录行号的方法...

如果需要在查询语句返回的列中包括一列以指示整个结果集中记录的行号,则ISO SQL: 2003标准建议的方法是提供ROW_NUMBER()/ RANK()函数. Oracle可以使用标准方法(版本8i或更高版本)或非标准ROWNUM. MS SQL Server在2005版中提供了ROW_NUMBER()函数. 但是在MySQL中似乎…

开发者必看!探秘阿里云Hi购季开发者分会场:海量学习资源0元起!

2019阿里云云上Hi购季活动已经于2月25日正式开启,从已开放的活动页面来看,活动分为三个阶段: 2月25日-3月04日的活动报名阶段、3月04日-3月16日的新购满返5折抢购阶段、3月16日-3月31日的续费抽豪礼5折抢购阶段。 活动核心亮点:…

疫情严重,潜伏期也有传染性?科技公司在行动

整理 | 阿司匹林出品 | CSDN云计算新型冠状病毒的感染人数仍在不断增加。根据1月26日的最新数据,全国新型冠状病毒感染的肺炎确诊2005例,疑似2684例,死亡56例。据央视报道,国家卫生健康委员会主任马晓伟在国新办新闻发布会上表示&…

python方法定义..._解析Python类中的方法定义

最近在学习类过程中,绑定方法这个概念没有理解透彻,所以在网上找了很多相关博客、文章研究到底是怎么一回事。因为有的文章所陈述与我在python3.5版本实际实验中有些出入,所以经过实践后总结出以下结论。对于Python类中,方法的定义…

阿里巴巴复杂搜索系统的可靠性优化之路

背景 搜索引擎是电商平台成交链路的核心环节,搜索引擎的高可用直接影响成交效率。闲鱼搜索引擎作为闲鱼关键系统,复杂度和系统体量都非常高,再加上闲鱼所有导购场景都依靠搜索赋能,搜索服务的稳定可靠成为了闲鱼大部分业务场景可…

Kubernetes 将何去何从?

戳蓝字“CSDN云计算”关注我们哦!作者 | Kevin Casey译者 | 弯月责编 | 唐小引封图 | CSDN 付费自图虫创意出品 | CSDN 云计算(ID:CSDNcloud)【导读】随着越来越多的人开始使用 Kubernetes,IT 领导者对新的一年有哪些期…

活体检测很复杂?仅使用opencv就能实现!(附源码)

什么是活体检测,为什么需要它? 随着时代的发展,人脸识别系统的应用也正变得比以往任何时候都更加普遍。从智能手机上的人脸识别解锁、到人脸识别打卡、门禁系统等,人脸识别系统正在各行各业得到应用。然而,人脸识别系…

Pod在多可用区worker节点上的高可用部署

一、 需求分析 当前kubernetes集群中的worker节点可以支持添加多可用区中的ECS,这种部署方式的目的是可以让一个应用的多个pod(至少两个)能够分布在不同的可用区,起码不能分布在同一个可用区,已达到高可用或者同…

揭秘:蚂蚁金服bPaaS究竟是什么?

去年9月,蚂蚁金服在杭州云栖ATEC发布了分布式金融核心套件bPaaS( Business Platform As a Service ),对外开放自身沉淀的“产品合约”、“资产交换”、“资产核心”、“会计核算”、“计价” 等金融核心组件,而这款号称…

云计算的 2020:云原生崛起,重新定义软件!

戳蓝字“CSDN云计算”关注我们哦!作者 | Ashish Sukhadeve译者 | 弯月责编 | 唐小引封图 | CSDN 付费自图虫创意出品 | CSDN 云计算(ID:CSDNcloud)随着 2006 年末 AWS S3 数据存储的问世,云计算发展成为了 IT 行业的三…

用PL/SQL Develpoer工具完成导入和导出

文章目录一、用PL/SQL Develpoer工具完成导入导出1. 导出2. 导入3. 补充前言:首先,我们导入导出数据,肯定是要通过oracle自带的可运行程序来完成数据的导入导出工作,imp.exe 和exp.exe这两个可运行文件都放在oracle安装目录下的BI…

关于Paxos 幽灵复现问题的看法

由于郁白之前写的关于Multi-Paxos 的文章流传非常广, 原文提出了一个叫"幽灵复现" 的问题, 认为这个是一个很诡异的问题, 后续和很多人交流关于一致性协议的时候, 也经常会提起这个问题, 但是其实这个问题我认为就是常见的"第三态"问题加了一层包装而已. …

idea spring boot 修改 html,js 等不用重启即时生效

1、【File】-【Settings】-【Build,Execution,Deplyment】-【Compiler】,选中打勾 Build project automatically 2、 组合键:ShiftCtrlAlt/,选择 Registry ,选中打勾 compiler.automake.allow.when.app.running” 3、找到你要运…

阿里巴巴微服务开源项目盘点(持续更新)

大前端、微服务、数据库、更多精彩,尽在开发者分会场 【Apache Dubbo】 Apache Dubbo 是一款高性能、轻量级的开源Java RPC框架,是国内影响力最大、使用最广泛的开源服务框架之一,它提供了三大核心能力:面向接口的远程方法调用&…

100行Python代码理解深度学习关键概念:从头构建恶性肿瘤检测网络

在构建乳腺癌预测神经网络过程中,我们主要分为3大部分: 1.用Python从零开始创建一个神经网络,并使用梯度下降算法训练模型。 2.在该神经网络中使用威斯康星乳腺癌数据集,根据9种不同的特征,预测肿瘤是良性还是恶性的…