内容简介:作者:Alex Leong重试是处理分布式系统中的部分或瞬态故障的基本机制。但重试也可能是危险的,如果做得不好,他们可以迅速将一个小错误升级为系统范围的中断。在这篇文章中,我们描述了我们如何在Linkerd 2.2里设计重试,使Linkerd能够在最小化风险的同时,自动提高系统可靠性。
作者:Alex Leong
重试是处理分布式系统中的部分或瞬态故障的基本机制。但重试也可能是危险的,如果做得不好,他们可以迅速将一个小错误升级为系统范围的中断。在这篇文章中,我们描述了我们如何在Linkerd 2.2里设计重试,使Linkerd能够在最小化风险的同时,自动提高系统可靠性。
将路由标记为可重试
在Linkerd 2.2里,我们引入了重试,就是Linkerd能够自动重试失败的请求。这使Linkerd能够自动处理服务中的部分或瞬态故障,而无需应用程序知道:如果请求失败,Linkerd可以再次尝试!结合Linkerd的 请求级负载平衡 ,这允许Linkerd处理各个pod的故障。
在Linkerd里,您将重试指定为服务配置文件的一部分(在 之前的博客文章 中介绍)。将路由标记为可重试就像添加isRetryable一样简单:设定true到相应的服务配置文件条目:
- name: HEAD /authors/{id}.json condition: method: HEAD pathRegex: /authors/[^/]*\\.json isRetryable: true
当然,在向路由添加重试行为之前,应该确保路由是幂等的(idempotent)。换句话说,对具有相同参数的相同路由的多次调用将没有不良影响。这很重要,因为重试(根据定义!)可能导致将同一请求的多个副本发送到服务。如果请求做了非幂等的(non-idempotent)事情,例如从您的银行帐户中减去一美元,您可能不希望它自动重试。
启用后,重试有两个重要参数:预算(budget)和超时(timeout)。让我们依次考虑这两个方面。
使用重试预算
将路由标记为可重试后,Linkerd允许您为服务配置重试预算。Linkerd附带了合理的默认值,但如果您想自定义预算,可以在服务配置文件中进行设置:
retryBudget: # The retryRatio is the maximum ratio of retries requests to original # requests. A retryRatio of 0.2 means that retries may add at most an # additional 20% to the request load. retryRatio: 0.2 # This is an allowance of retries per second in addition to those allowed # by the retryRatio. This allows retries to be performed, when the request # rate is very low. minRetriesPerSecond: 10 # This duration indicates for how long requests should be considered for the # purposes of calculating the retryRatio. A higher value considers a larger # window and therefore allows burstier retries. ttl: 10s
Linkerd使用重试预算,较使用最大重试次数配置重试的常规做法,是更好替代方法。我们花一点时间来理解为什么。
为什么预算而不是最大重试次数?
首先,一些背景。配置重试的最常用方法,是指定在放弃之前执行的最大重试次数。对于使用网络浏览器的任何人来说,这是一个熟悉的想法:您尝试加载网页,如果没有加载,则再试一次。如果仍然无法加载,则第三次尝试。最后您放弃了。
不幸的是,以这种方式配置重试至少有两个问题:
选择最大重试次数是猜谜游戏。您需要选择一个足够高的数字,以便在出现某种故障时发挥作用,但不要太高,以至于当系统真正失败时会在系统上产生额外负载。在实践中,您通常会从帽子中选择最大重试次数(例如3),并希望获得最佳效果。
以这种方式配置的系统易受重试风暴的影响。当一个服务开始出现大于正常的故障率时,重试风暴开始。这会导致其客户端重试这些失败的请求。重试带来的额外负载,会导致服务进一步减速,并使更多请求失败,从而触发更多重试。如果每个客户端配置为最多重试3次,则可以将发送的请求数量翻两番!更糟糕的是,如果任何客户端的客户端配置了重试,则重试次数会成倍增加,并且可以将少量错误转化为自我造成的拒绝服务攻击。
为了避免这些问题,Linkerd使用重试预算。Linkerd不是为每个请求指定固定的最大重试次数,而是跟踪常规请求和重试之间的比率,并将此数字保持在限制之下。例如,您可以指定要重试最多添加20%的请求。然后,Linkerd将尽可能多地重试,同时保持该比率。
因此,使用重试预算可以明确在提高成功率和额外负载之间进行权衡。您的重试预算正是您的系统愿意从重试中接受的额外负载。
(最后,Linkerd的重试预算还包括允许的最小重试次数,这将是唯一允许的,与比率无关。这使得Linkerd可以在非常低的流量系统中重试。)
设置每个请求的超时
除了预算之外,重试还按每个请求的超时参数。超时可确保始终失败的请求最终会返回响应,即使该响应失败也是如此。超时时,Linkerd将取消请求并返回HTTP 504响应。
与重试预算类似,重试超时具有可在服务配置文件中覆盖的合理默认值:
- name: HEAD /authors/{id}.json condition: method: HEAD pathRegex: /authors/[^/]*\\.json timeout: 50ms
谁管有重试行为?客户端还是服务器?
您可能已经注意到上面的配置片段中的有趣内容。在“传统”重试系统(例如Web浏览器)中,是在客户端上配置重试行为,毕竟,这是重试实际发生的地方。但是在上面的服务配置文件中,我们将在服务器端指定重试政策。
能够将政策附加到服务器端,但客户端必须遵守该政策,这是Linkerd服务配置文件方法的基本优势之一。重试配置在逻辑上属于服务级别(“这是您应该和我说话的方式”)。由于Linkerd控制客户端和服务器行为,我们可以正确的方式执行此操作:服务配置文件允许服务准确发布“这是我希望您与我交谈的方式”,通过Linkerd的所有流量,无论来源如何,会尊重这种行为。太酷了!
把它们放在一起
我们已经展示了如何通过组合超时、预算和可重试性来配置Linkerd的重试行为。现在让我们将它们放在一起进行简短的演示。如果您有一个终端窗口和一个Kubernetes集群,您可以在家里跟随。
我们首先安装Linkerd和我们的样本书应用程序:
$ linkerd install | kubectl apply -f - $ curl https://run.linkerd.io/bookapp.yml | linkerd inject - | kubectl apply -f - $ linkerd check
关于这个应用程序,我们可以注意到的一件事是,从书籍服务到作者服务的请求的成功率非常低:
$ linkerd routes deploy/books --to svc/authors ROUTE SERVICE SUCCESS RPS LATENCY_P50 LATENCY_P95 LATENCY_P99 [DEFAULT] authors 54.24% 3.9rps 5ms 14ms 19ms
为了更好地了解这里发生了什么,让我们为作者服务添加一个服务配置文件,从Swagger定义生成:
$ curl https://run.linkerd.io/booksapp/authors.swagger | linkerd profile --open-api - authors | kubectl apply -f - $ linkerd routes deploy/books --to svc/authors ROUTE SERVICE SUCCESS RPS LATENCY_P50 LATENCY_P95 LATENCY_P99 DELETE /authors/{id}.json authors 0.00% 0.0rps 0ms 0ms 0ms GET /authors.json authors 0.00% 0.0rps 0ms 0ms 0ms GET /authors/{id}.json authors 0.00% 0.0rps 0ms 0ms 0ms HEAD /authors/{id}.json authors 50.85% 3.9rps 5ms 10ms 17ms POST /authors.json authors 0.00% 0.0rps 0ms 0ms 0ms [DEFAULT] authors 0.00% 0.0rps 0ms 0ms 0ms
有一件事是清楚的,从书籍到作者的所有请求都是针对HEAD /authors/{id}.json路线,这些请求在大约50%的时间内失败。为了纠正这个问题,让我们编辑作者服务配置文件,并使这些请求可以重试:
$ kubectl edit sp/authors.default.svc.cluster.local [...] - condition: method: HEAD pathRegex: /authors/[^/]*\\.json name: HEAD /authors/{id}.json isRetryable: true ### ADD THIS LINE ###
在编辑服务配置文件后,我们看到成功率几乎立即有所改善:
$ linkerd routes deploy/books --to svc/authors -o wide ROUTE SERVICE EFFECTIVE_SUCCESS EFFECTIVE_RPS ACTUAL_SUCCESS ACTUAL_RPS LATENCY_P50 LATENCY_P95 LATENCY_P99 DELETE /authors/{id}.json authors 0.00% 0.0rps 0.00% 0.0rps 0ms 0ms 0ms GET /authors.json authors 0.00% 0.0rps 0.00% 0.0rps 0ms 0ms 0ms GET /authors/{id}.json authors 0.00% 0.0rps 0.00% 0.0rps 0ms 0ms 0ms HEAD /authors/{id}.json authors 100.00% 2.8rps 58.45% 4.7rps 7ms 25ms 37ms POST /authors.json authors 0.00% 0.0rps 0.00% 0.0rps 0ms 0ms 0ms [DEFAULT] authors 0.00% 0.0rps 0.00% 0.0rps 0ms 0ms 0ms
成功率看起来很好,但p95和p99延迟有所增加。这是可以预料到的,因为重试需要时间。但是,我们可以通过设置超时,Linkerd 2.x的另一个新功能,在我们愿意等待的最长持续时间来限制此操作。出于本演示的目的,我将设置25ms的超时。您的结果将根据系统的特性而有所不同。
$ kubectl edit sp/authors.default.svc.cluster.local [...] - condition: method: HEAD pathRegex: /authors/[^/]*\\.json isRetryable: true name: HEAD /authors/{id}.json timeout: 25ms ### ADD THIS LINE ###
我们现在看到成功率略有下降,因为有些请求超时,但尾部延迟已大大减少:
$ linkerd routes deploy/books --to svc/authors -o wide ROUTE SERVICE EFFECTIVE_SUCCESS EFFECTIVE_RPS ACTUAL_SUCCESS ACTUAL_RPS LATENCY_P50 LATENCY_P95 LATENCY_P99 DELETE /authors/{id}.json authors 0.00% 0.0rps 0.00% 0.0rps 0ms 0ms 0ms GET /authors.json authors 0.00% 0.0rps 0.00% 0.0rps 0ms 0ms 0ms GET /authors/{id}.json authors 0.00% 0.0rps 0.00% 0.0rps 0ms 0ms 0ms HEAD /authors/{id}.json authors 97.73% 2.9rps 49.71% 5.8rps 9ms 25ms 29ms POST /authors.json authors 0.00% 0.0rps 0.00% 0.0rps 0ms 0ms 0ms [DEFAULT] authors 0.00% 0.0rps 0.00% 0.0rps 0ms 0ms 0ms
请注意,由于直方图分段工件,p99延迟似乎大于我们的25ms超时。
总结
在这篇文章中,我们描述了Linkerd如何以最小化系统风险的方式自动重试请求。我们描述了为什么在服务器,而不是客户端级别,指定了重试行为,我们向您介绍了如何在演示应用程序中部署服务的重试和超时功能。
重试是Linkerd可靠性路线图中的一大进步。服务配置文件、重试和诊断的交集是Linkerd特别令人兴奋的领域,您可以期待未来版本中 更酷的功能 。敬请期待!
喜欢这篇文章?Linkerd是一个社区项目,由CNCF托管。如果您有功能请求、问题或评论,我们很乐意让您加入我们快速发展的社区!Linkerd的 仓库在GitHub上 ,我们在Slack、Twitter和邮件列表上拥有一个蓬勃发展的社区。快来加入吧!
KubeCon + CloudNativeCon和Open Source Summit大会日期:
- 会议日程通告日期:2019 年 4 月 10 日
- 会议活动举办日期:2019 年 6 月 24 至 26 日
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 架构设计(7)——如何设计一个架构
- 架构设计(8)—高可用架构设计
- 如何设计实时数据平台(设计篇)
- Token经济设计专家叶开:Token设计画布与10大设计模式
- 数据可视化设计(1)情感化设计指导可视化设计理念
- 架构设计笔记(八):详细方案设计
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Music Recommendation and Discovery
Òscar Celma / Springer / 2010-9-7 / USD 49.95
With so much more music available these days, traditional ways of finding music have diminished. Today radio shows are often programmed by large corporations that create playlists drawn from a limited......一起来看看 《Music Recommendation and Discovery》 这本书的介绍吧!