Appearance
- Overload Control for Scaling WeChat Microservices
研究背景与问题 (BACKGROUND & OVERLOAD IN WECHAT)
- 微信系统架构
- 类型: 基于微服务架构,服务间关系构成有向无环图 (DAG)。
- 服务分类:
- 入口服务 (Entry Service): 用户请求的起点 (in-degree=0)。
- 中间层服务 (Leap Service): 可调用其他服务 (out-degree>0)。
- 基础服务 (Basic Service): 服务调用的终点 (out-degree=0),如账户、资料、消息收件箱等。
- 系统规模:
- 超过 3000 个服务,运行在超过 20000 台机器上。
- 系统动态性强,平均每天近千次变更。
- 工作负载波动大,节假日峰值可达日常平均的 10 倍。
- 核心研究问题:大规模微服务下的过载控制
- 关键挑战:后续过载 (Subsequent Overload)
- 定义: 一个上游任务的成功,依赖于对下游过载服务的多次成功调用。
- 具体场景:
- 1: 多次调用同一个已过载的服务 (如 A 调用 M 两次)。
- 2: 分别调用多个不同的已过载服务 (如 A 调用 M 和 N)。
- 问题根源: 简单的随机丢弃策略会导致任务成功率急剧下降 (例如,若单次调用成功率为 50%,连续两次调用的成功率仅为 25%),造成资源浪费和“服务假死”现象。
- 架构带来的挑战:
- 无单一入口: 传统的网关集中式监控失效。
- 调用路径复杂: 难以精确判断应丢弃哪类请求。
- 协调成本高: 在快速演进的复杂系统中,服务间的强协调机制难以维护。
- 关键挑战:后续过载 (Subsequent Overload)
- 微信系统架构
核心方法 (DAGOR OVERLOAD CONTROL)
- 设计原则
- 服务无关 (Service Agnostic): 控制逻辑与业务逻辑解耦,普适于各类服务。
- 独立但协作 (Independent but Collaborative): 各服务独立决策,但通过协作机制共同应对过载。
- 高效且公平 (Efficient and Fair): 最小化失败任务的资源浪费,保证上游服务在下游过载时仍能维持饱和吞吐。
- 1. 过载检测 (Overload Detection)
- 机制: 在每个服务器上进行去中心化的本地监控。
- 核心指标: 请求在等待队列中的平均时间 (Queuing Time)。
- 选择理由:
- 相比响应时间 (Response Time):排队时间只反映本地服务器的处理能力,不受下游服务响应慢的影响,更准确,避免误报。
- 相比CPU利用率:高CPU不一定等于过载,只要请求能被及时处理。
- 实现细节: 采用窗口期(如每秒或每2000个请求)进行统计,微信实践中阈值设为 20ms。
- 2. 服务准入控制 (Service Admission Control)
- 基础:双层优先级系统
- 业务优先级 (Business Priority):
- 静态优先级,在入口服务层根据业务重要性分配 (如:登录 > 支付 > 发消息)。
- 存储在可复制的哈希表中。
- 在整个请求调用链中向下传递。
- 用户优先级 (User Priority):
- 动态优先级,用于在同业务优先级内进行细粒度控制,解决后续过载问题。
- 通过
hash(用户ID)
生成。 - 哈希函数每小时更换,以保证用户间的公平性。
- 同样在整个调用链中传递。
- 业务优先级 (Business Priority):
- 机制 A:自适应准入控制 (Adaptive Admission Control)
- 目标: 根据负载动态调整服务器的准入优先级阈值
(α%, β%)
。 - 方法: 基于直方图的高效调整算法。
- 服务器维护一个按
(业务优先级, 用户优先级)
索引的请求计数器直方图。 - 根据当前是否过载,计算下一个周期的目标接纳率(过载则降低
α%
,不过载则提升β%
)。 - 利用直方图的累加和,一次性计算出能满足目标接納率的新的优先级阈值,避免了低效的线性或二分搜索。
- 服务器维护一个按
- 目标: 根据负载动态调整服务器的准入优先级阈值
- 机制 B:协作式准入控制 (Collaborative Admission Control)
- 目标: 在上游服务处提前拒绝注定会被下游丢弃的请求,节省网络和下游服务器资源。
- 方法: 捎带 (Piggybacking) 机制。
- 下游服务 (M) 在其响应消息中,捎带上自己当前的准入优先级阈值。
- 上游服务 (A) 收到响应后,缓存下游服务 M 的准入门槛。
- 当 A 准备再次向下游 M 发送请求时,先使用缓存的阈值进行本地预检查,提前丢弃不满足条件的请求。
- 基础:双层优先级系统
- 设计原则
实验设计 (EVALUATION)
- 实验环境:
- 模拟一个上游消息服务 A 和一个下游加密服务 M。
- 服务 M 被部署在3台服务器上,处理能力上限为 750 QPS。
- 工作负载 (Workloads):
- M¹: 简单过载 (A 调用 M 一次)。
- M², M³, M⁴: 后续过载 (A 分别调用 M 2, 3, 4 次)。
- 混合负载: 均匀混合 M¹ 到 M⁴ 的请求。
- 对比方案:
- CoDel, SEDA, Naive (随机丢弃)。
- DAGOR 的变种 (使用响应时间作为检测指标)。
- 实验环境:
关键结果 (Key Results)
- 检测指标对比: 使用排队时间比使用响应时间作为过载指标更精确,能更好地反映真实负载,避免过早地触发限流。
- 后续过载下的性能:
- 在后续过载场景 (M²) 下,DAGOR 的请求成功率比 CoDel 和 SEDA 高出约 50%,接近理论最优值。
- 随着后续调用次数增加 (M³、M⁴),DAGOR 的优势愈发明显。
- 公平性:
- 在混合负载下,DAGOR 对不同类型的请求(简单 vs 后续过载)能保持大致相同的成功率,体现了公平性。
- 相比之下,CoDel 明显偏向于处理简单的 M¹ 请求,对复杂任务不友好。
技术贡献 (Technical Contribution)
- 首次识别并定义了微服务架构中的后续过载 (Subsequent Overload) 这一关键问题。
- 提出使用 排队时间 (Queuing Time) 作为一种更鲁棒的本地化过载检测指标。
- 设计了业务 + 用户双层优先级体系,确保同一请求在调用链中决策的一致性,从而有效解决了后续过载问题。
- 实现了基于直方图的高效自适应算法,用于实时调整准入门槛。
- 引入了通过捎带机制实现的轻量级协作控制,实现了负载的早期丢弃。
原文: 《Overload Control for Scaling WeChat Microservices》