惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Microsoft Azure Blog
Microsoft Azure Blog
Cloudbric
Cloudbric
I
InfoQ
V
V2EX
博客园_首页
The Register - Security
The Register - Security
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
S
Secure Thoughts
Vercel News
Vercel News
Forbes - Security
Forbes - Security
云风的 BLOG
云风的 BLOG
PCI Perspectives
PCI Perspectives
L
LINUX DO - 最新话题
D
DataBreaches.Net
H
Hacker News: Front Page
Application and Cybersecurity Blog
Application and Cybersecurity Blog
B
Blog RSS Feed
A
About on SuperTechFans
N
News and Events Feed by Topic
Apple Machine Learning Research
Apple Machine Learning Research
Help Net Security
Help Net Security
Attack and Defense Labs
Attack and Defense Labs
N
Netflix TechBlog - Medium
Spread Privacy
Spread Privacy
F
Full Disclosure
Recorded Future
Recorded Future
AWS News Blog
AWS News Blog
博客园 - 【当耐特】
The Cloudflare Blog
T
Threatpost
T
Tor Project blog
Google DeepMind News
Google DeepMind News
C
CXSECURITY Database RSS Feed - CXSecurity.com
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Recent Announcements
Recent Announcements
M
MIT News - Artificial intelligence
A
Arctic Wolf
C
Check Point Blog
Stack Overflow Blog
Stack Overflow Blog
T
Threat Research - Cisco Blogs
Security Archives - TechRepublic
Security Archives - TechRepublic
Hacker News - Newest:
Hacker News - Newest: "LLM"
WordPress大学
WordPress大学
Cyberwarzone
Cyberwarzone
小众软件
小众软件
C
Cyber Attacks, Cyber Crime and Cyber Security
P
Proofpoint News Feed
Security Latest
Security Latest
The Last Watchdog
The Last Watchdog

卡瓦邦噶!

服务器高性能网络调优 | 卡瓦邦噶! 为何写作 | 卡瓦邦噶! 读《金阁寺》 | 卡瓦邦噶! 雨季又来 | 卡瓦邦噶! MTU Probe 引起的初始延迟 | 卡瓦邦噶! 3.5 秒的固定延迟问题 | 卡瓦邦噶! 学习网络的一点经验 | 卡瓦邦噶! ARP 问题诊断 | 卡瓦邦噶! 网络断断续续…… | 卡瓦邦噶! Piccolo P2P 镜像分发 | 卡瓦邦噶! 一起看电影 | 卡瓦邦噶! 《征服C指针》 | 卡瓦邦噶! 我的姥姥 | 卡瓦邦噶! Python的哲学 Python 3.5的新特性 学校不教的计算机课 垃圾回收(GC)的三种基本方式 在编程中体验纯粹的快乐 从《美丽新世界》谈自由 在快钱实习 迷人的嗓音和迷人的故事——《Sleepyhead》 Python 的十个自然语言处理工具 记一个愚蠢的bug 一年炉石传说的游戏体验 《以撒的结合:重生》网页版图鉴 分清 C++的指针、引用和数组 笑话三则 自由比皇帝更伟大——《悲惨世界》笔记 Git 10 周年访谈:Linus 讲述背后故事 用 0x3f3f3f3f 设定最大int值的优点 Joel给计算机系学生的建议 一个词法分析器的简单实现 怎样才算健康的生活方式 MacVim 配置攻略 学习培训课程的视频效果好吗? 语言的控制 可悲的大多数 CSS样式思维导图 2014年终总结 奥巴马成为首位写程序的美国总统 青岛老城区的下水道好在哪里? 做优秀 UI 的七个建议(第二部分) 选择爱情的骑士 Git简明教程 Java集合总览 读 《1984》 java问答:终极父类(六)——等待/唤醒和接口 Java 问答:终极父类(五)——toString() Hyperlapse快速视频背后的技术细节 平庸之恶 Java程序员须知的七个日志管理工具 苏州 逛书摊随想 关于考试作弊 你的工作不仅仅是编程 推荐在线学习Java的英文资源 关注女性命运——《千禧年三部曲》 用好你的幻灯片——《演说之禅》 使用ReentrantLock和Lambda表达式让同步更纯净 新手学编程,从哪里开始? 程序员都是工程师吗? 不要学习代码,要学会思考 Java 问答:终极父类(四)——hashCode() Java 问答:终极父类(三)——finalize()和 getClass() 程序员职业之路的选择 我是一名摄影家 写给何小树的城市指南 为什么一些语言会比别的快? Java的常见误区与细节 跟朋友在一起玩游戏 死神永生——读《三体》 五种类型的程序员 创业圣经——读《黑客与画家》 纪念加西亚·马尔克斯 Junit中处理异常的另一种方式:catch-exception Java8采用Martin Fowler的方法创建内部DSL Linux HotSopt虚拟机GC线程的CPU占用率 J2EE概念介绍 如何成为一名黑客 Java 问答:终极父类(二)——equals()方法 为什么我喜欢Java Java 问答:终极父类(一)——clone()方法 七个改变世界的Java项目 java中默认类型转换的小问题 传统与创新 欢迎来到互联网 莫言和马尔克斯——读《生死疲劳》 位运算的妙用 读《人为什么活着》 写博客教会我的事情 中国特色操作系统 2013年总结 《永不妥协》影评 恨不相逢未嫁时——《廊桥遗梦》影评 如何优雅地使用PPT 给明年依然年轻的我们 天才与柱子 黑客守则和黑客精神 Looking for Freedom——《被解救的姜戈》 简洁之道
系统的过载(Overload)以及处理思路
laixintao · 2022-05-29 · via 卡瓦邦噶!

本文所谈到的过载,容易和雪崩混淆。雪崩指的是在分布式系统中,某一个依赖无法正常提供服务,但是系统无法屏蔽掉这个依赖,最终导致整个系统都无法提供服务了。

过载指的是某一个服务所收到的请求量原大于它能处理的请求。

所以后续的讨论使用过载这个词,虽然有的时候我们在讨论相同的问题,但是用的是“雪崩”这个词。

对于过载,似乎有一个很简单的解决方法:现在很多系统的设计都已经考虑好限流了。即,假如某一个系统能处理的 QPS 是 1000,那么它只会同时允许 1000 个请求进入处理,当第 1001 个请求来的时候,会迅速得到错误,直接返回。这样保护系统总是可以成功处理 1000 个请求的。

这就是 Rate limit, 一个典型的 overload protector. Rate limit 有很多实现的方法:Token bucket, Leaky bucket, 等等。

然而这样就足够了吗?

想象这样一种情况:有一个网站(比如您当前正在阅读的这个博客),所能够处理的 HTTP 请求是 1k/s. 但是目前有 1万 个访客正在访问,然后触发了网关(比如说是 Nginx)的限流机制,对于每秒钟第 1000 个之后的请求都直接访问 429 Too many requests.

这样的话,网站本身每秒都在处理 1000 个请求,看起来是在正常工作的,但是对于终端的用户来说呢?他们能正常浏览网页吗?答案是不能的。因为,拿博客的首页来说,一共要发送 61 个 HTTP 请求才能正常显示。也就是说,每一个用户都需要成功拿到 61 个 HTTP 的响应才能看到一个完整的网页,否则,可能缺失一些 css 文件导致网站的格式显示不正确;或者缺失了某些图片导致不知道内容在说的什么;或者无法请求某些 js 导致部分功能缺失。为了看到完整的网页,他们可能重新刷新网页,进一步加剧了当前网站承受的总流量。

再考虑这样一种情况。在一个微服务的系统中,为了展示一个商品的详细信息,“商品微服务” 需要调用3次“用户微服务”,目的分别是:

  1. 拿到用户所在的地区,用来计算运费;
  2. 拿到用户的会员等级,渲染优惠;
  3. 拿到用户当前账户中的积分信息,渲染出来如果使用积分的话可以优惠多少钱;

假如“用户微服务”过载的话,用户微服务对于所有的请求来源进行限流,那么现在这三个请求每一个都可能失败,每一个失败了都无法成功渲染出来商品详细信息。

还有一种情况。假设某一个服务发现系统使用 Etcd 这种带 lease 的数据库作为后端依赖。一个服务注册上之后,需要不断 renew lease, 才能保持在线上。如果它挂了,不再 renew lease,那么当 lease 过期之后,Etcd 就会将其从数据库中删除掉。

某一天,这个系统重启了,所有的服务都开始重新注册自己,请求量太大导致 Etcd 过载了。为了保护自己,Etcd 也有 Rate limit 机制,它只允许 3000 个请求同时处理,对于第 3001 个请求也会直接返回错误。这时候,有一些服务能够注册成功, 但是后续的 renew lease (keepalive) 请求可能失败。这样,即使 Etcd 能够成功处理 3000 个注册请求,但是这些注册功能的服务因为 keepalive 请求无法被接受,所以不得不重新注册自己。就会导致 Etcd 一直处于一种 overload 的状态,永远无法恢复。

以上几种情况,都是在有 Rate limiter 的情况下,系统依然会被 overload。

Overload 的时候,总请求量是比容量要大的,那么我们的解决思路就是,要保证总请求量随时间不断减少,最终,总请求量在能够处理的容量之内。虽然有些请求可能失败,但是他们最终的重试是会成功的。换句话说,要保证我们处理的请求都是“有效的”请求。

举一个反例:网站使用队列来缓存住超过容量限制的 HTTP 请求,然后不断从队列中取出来请求处理。这之所以是一个糟糕的方案,是因为在 HTTP 的场景中,如果一个用户打不开网页,那么他会刷新而不是等在这里。所以网站服务器从队列中拿出来的请求总是用户已经放弃的请求,那么一直在处理“无效”的请求了。

一些可以考虑的思路如下。

按照上下文进行限流

当过载的时候,我们要保证依然在容量限制内的数量的用户是可以正常服务的。但是不能单纯的从请求的角度来进行限流。而是应该加入业务上下的维度。比如:

  • 假如一个用户打开了某一个页面,要保证后续的操作都是成功的,至少可以完成一次交易;假如某一个用户已经被 rate limiter 失败了,那么这个用户的请求我们都让它失败掉,不要再处理他的请求浪费资源了;
  • 或者按照用户 id 进行 sharding,只保护某一部分用户;过一段时间保护另一部分用户;

原子化调用

在上文中第二个例子中,可以考虑将三次请求变成一次请求。这样按照请求维度的限流依然是有效的。

切换成异步链路

对于某些情况,可以考虑使用上面的“反例”。比如说用户的付款请求,如果遇到了失败,那么用户很可能放弃这笔交易。我们可以考虑使用队列来让付款请求排队,尽可能让付款请求有更大的能够成功处理的机会:

  • 显示明确的处理中的字样,尽量给与用户安抚;
  • 如果用户尝试取消,弹出确认提示可以取消付款,交易尚未发生,但是鼓励继续等待;
  • 对于信用好的用户,或者单价低的订单,考虑先推进交易,异步从账户中扣款;

临时的降级(断路)

在雪崩的情况下能够有应急的方式临时屏蔽掉一些消耗资源的特性。

比如在上述 Etcd 的场景中,我们可以考虑,当服务首次注册成功的时候,将 lease 的时间设置为 20min,在第15min 的时候开始尝试 renew,如果失败,以指数级的时间退避重试。如果重试的次数比较少就成功 renew 了,就将 lease 的时间设置为 10min;下一次再缩短 lease,直到 lease 是一个足够短,满足服务健康检查的时间。这样可以在短期内给与 Etcd 足够的时间去恢复,保证它当前正在处理的请求都是最终的要求(指的是,把服务注册上去是第一要务,健康检查踢掉异常服务是次要任务,可以暂时降级)。