作者:Alex Leong

重试是处理分布式系统中的部分或瞬态故障的基本机制。但重试也可能是危险的,如果做得不好,他们可以迅速将一个小错误升级为系统范围的中断。在这篇文章中,我们描述了我们如何在Linkerd 2.2里设计重试,使Linkerd能够在最小化风险的同时,自动提高系统可靠性。

将路由标记为可重试

在Linkerd 2.2里,我们引入了重试,就是Linkerd能够自动重试失败的请求。这使Linkerd能够自动处理服务中的部分或瞬态故障,而无需应用程序知道:如果请求失败,Linkerd可以再次尝试!结合Linkerd的请求级负载平衡,这允许Linkerd处理各个pod的故障。

在Linkerd里,您将重试指定为服务配置文件的一部分(在之前的博客文章中介绍)。将路由标记为可重试就像添加isRetryable一样简单:设定true到相应的服务配置文件条目:

- name: HEAD /authors/{id}.jsoncondition:method: HEADpathRegex: /authors/[^/]*\\.jsonisRetryable: 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}.jsoncondition:method: HEADpathRegex: /authors/[^/]*\\.jsontimeout: 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: HEADpathRegex: /authors/[^/]*\\.jsonname: HEAD /authors/{id}.jsonisRetryable: 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: HEADpathRegex: /authors/[^/]*\\.jsonisRetryable: truename: HEAD /authors/{id}.jsontimeout: 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 日

KubeCon + CloudNativeCon和Open Source Summit赞助方案
KubeCon + CloudNativeCon和Open Source Summit多元化奖学金现正接受申请
KubeCon + CloudNativeCon和Open Source Summit即将首次合体落地中国

我们如何在Linkerd 2.2里设计重试相关推荐

  1. 我们如何在Linkerd 2.2里设计重试 1

    我们如何在Linkerd 2.2里设计重试 作者:Alex Leong 重试是处理分布式系统中的部分或瞬态故障的基本机制.但重试也可能是危险的,如果做得不好,他们可以迅速将一个小错误升级为系统范围的中 ...

  2. SAP UI5 应用开发教程之四十八 - 如何在 SAP UI5 应用里开发条形码扫描功能试读版

    一套适合 SAP UI5 初学者循序渐进的学习教程 教程目录 SAP UI5 本地开发环境的搭建 SAP UI5 应用开发教程之一:Hello World SAP UI5 应用开发教程之二:SAP U ...

  3. SAP UI5 应用开发教程之四十五 - 如何在 SAP UI5 应用里使用 jQuery 和原生的 DOM API

    一套适合 SAP UI5 初学者循序渐进的学习教程 教程目录 SAP UI5 本地开发环境的搭建 SAP UI5 应用开发教程之一:Hello World SAP UI5 应用开发教程之二:SAP U ...

  4. 如何在 SAP UI5 应用里显示 PDF 文件试读版

    一套适合 SAP UI5 初学者循序渐进的学习教程 本专栏计划的文章数在 300 篇左右,到 2022年12月23日为止,目前已经更新了 155 篇,专栏完成度为 51.6%,完成度已经超过了一半了. ...

  5. SAP UI5 应用开发教程之五十九 - 如何在 SAP UI5 应用里显示世界地图试读版

    一套适合 SAP UI5 初学者循序渐进的学习教程 教程目录 SAP UI5 本地开发环境的搭建 SAP UI5 应用开发教程之一:Hello World SAP UI5 应用开发教程之二:SAP U ...

  6. 用bbp公式计算pi_家用配电箱里设计几个回路合适?用这个公式,计算起来很方便...

    原标题:家用配电箱里设计几个回路合适?用这个公式,计算起来很方便 确定数量 家庭配电箱的数量应该是1(主开关)+2(1~2个照明回路)+a(房间回路)+b(大功率回路). 照明回路数量,由房间面积大小 ...

  7. 计算机单元格选项,如何在excel单元格里设置下拉选项

    我们在编辑excel表格的时候,填写的很多内容都是相同的,那么我们如何在excel单元格里设置下拉选项呢?下面学习啦小编告诉你! 在excel单元格里设置下拉选项的方法 首先我们先打开excel打开之 ...

  8. 在Layui框架里设计一个评论列表的前端界面

    在Layui框架里设计一个评论列表的前端界面 本想找个模板随便写个评论界面,结果找了大半天,木有找到,只能自己动手丰衣足食了.可以点击删除,点击加载更多也能拼接获取更多内容,只是写了个大概模拟逻辑的功 ...

  9. 如何在JavaScript中直观地设计状态

    by Shawn McKay 肖恩·麦凯(Shawn McKay) 如何在JavaScript中直观地设计状态 (How to visually design state in JavaScript) ...

最新文章

  1. 浅谈python语言_浅谈Python语言基础知识点!
  2. python单元测试的应用_单元测试pythongui应用程序的推荐方法是什么?
  3. Win7系统下调整硬盘分区大小给C盘更多的空间
  4. 雷军说小米综合净利润率永远不超过5%,玺哥相信他是真心的!
  5. delphi 查找指定后缀名的函数_Excel明星函数系列2:掌握这5类VLOOKUP查询方法,搞定查询...
  6. C语言内存泄漏问题检视方法
  7. 王亚叶:洞悉客户心声用大数据运营
  8. webmagic模拟登陆获取cookie_Python3爬虫:selenium模拟登录获取cookie提取数据,存入数据库MySQL...
  9. windows 2003活动目录更名操作[图]
  10. greenshot滚屏截图_Greenshot是一款免费的轻量级屏幕截图实用程序,具有许多有用的功能...
  11. 如何选择适合的伺服电机?
  12. C语言——单词精确查找
  13. 清除计算机用户缓存,清理缓存怎么清理_如何清理电脑缓存垃圾-win7之家
  14. idea中Empty tag doesn‘t work in some browsers 浏览器中一片空白,没有渲染样式,
  15. Inferior 1 (process xxx) exited with code 0177
  16. 使用Node搭建reactSSR服务端渲染架构
  17. Android入门篇(一)了解androidstudio开发软件
  18. 基于单片机的环境监测调节系统设计(#0516)
  19. 王者荣耀戈娅的攻击阈值是多少 王者荣耀戈娅怎么连招
  20. Python3中省略号(...)用法介绍

热门文章

  1. 脚本不得关闭非脚本打开的窗口。_selenium自动化测试:2.录制和导出脚本
  2. echarts柱状图 与轴不重叠_如何让柱状图柱子不挨着坐标轴,就像图片这样
  3. 电脑编程python和c加加语言的区别_小猿圈之Bash 和 Python 编程语言优缺点
  4. 个人支付宝收款页面,对接当面付接口
  5. PHPCMS资源网站源码软件源码下载站网站源码
  6. KODExplorer可道云-资源管理器(芒果云)
  7. 流星数据恢复软件 v2.4
  8. 三百英雄服务器维护2020,酸败英雄梦服维护公告《300英雄梦服》将定于2020年8月3...
  9. 仿英雄联盟比赛直播网页模板
  10. 简约风车壁纸自动采集小程序源码