腾讯官方写论文:微信的技术架构有多复杂

更新时间:2018-11-30 09:16:26点击次数:1256次字号:T|T    

腾讯旗下的微信从一个通信工具变成一个庞大平台,究竟经历了什么?微信开发者团队最近一篇论文“Overload Control for Scaling WeChat Microservices(超大规模微信微服务中的过载控制)”透露了部分细节,主要讲述了微服务的过载控制。

基于这篇论文,本文核心要点有二。其一,解析微信的后端; 第二,解析微信五年生产化运行过程中,得到实践检验的过载控制系统DAGOR的设计思路。这套系统在设计上专门考虑到微服务架构的特殊性,如果你希望为自己的微服务制定策略,那么本文无疑是一份极好的上手指南。

截至目前,微信后端共包含超过3000项移动服务,其中包括即时消息收发、社交网络、移动支付以及第三方验证等等。该平台每天接收到的外部请求量在 10^10-10^11次之间,其中每一项请求都会触发更多的内部微服务请求,这意味着微信后端整体每秒需要处理数亿次请求。

微信的微服务系统能够在微信业务系统中的2万多台设备上运行超过3000项服务。而随着微信的广泛普及,这一数字仍然不断增加……伴随着微信的不断发展,微服务系统一直在快速迭代并进行服务更新。举例来说,从2018年3月到5月,微信的微服务系统每天平均经历近千次变化。

微信将其微服务分类为“入口跳转”服务(用于接收外部请求的前端服务)、“共享跳转”服务(中间层协调服务)以及“基本服务”(不向任何其它服务扇出,因此可充当请求接收方的服务)。


图:微信的微服务架构


以普通的单日运行场景为例,微信的峰值请求率约为每日平均值的3倍。在一年中的某些特定时段(例如在中国的农历新年期间),峰值工作负载甚至有可能增长至每日平均值的10倍。

基于大规模微服务平台的过载控制挑战

“Overload control… is essential for large-scale online applications that need to enforce 24×7 service availability despite any unpredictable load surge.”(过载控制……对于大规模在线应用程序而言至关重要,这些应用程序需要在遭遇不可预测的负载激增时实现24 x 7全天候服务可用性。)

传统的过载控制机制专门面向具有少量服务组件、“入口”相对狭窄且依赖性较为普通的场景所设计。

“… modern online services are becoming increasingly complex in their architecture and dependencies, far beyond what traditional overload control was designed for…”(…现代在线服务在架构与依赖性方面则变得越来越复杂,这远远超出了传统过载控制方案的设计目标。)

•由于发送至微信后端的服务请求不存在单一入口点,因此在全球入口点(网关)进行集中式负载监控的传统方案将不再适用。

•特定请求中的服务调用图可能取决于因请求而异的数据与服务参数,即使是相同类型的请求也可能存在这种差异。因此,当特定服务出现过载时,很难确定应该删除哪些类型的请求以缓解过载情况。

•过多的请求中止(特别是在调用图中较深或请求流程内偏后的部分时)会浪费计算资源,并带来影响用户体验的高延迟问题。

•由于微信的服务DAG(有向无环图)极其复杂且不断发展,因此用于实现高效跨服务协调的维护成本与系统开销都将超出可承受范围。

由于某项服务可能会对其所依赖的服务发出多次请求,并且有可能向多项后端服务发出请求,因此我们必须高度关注过载控制。对于调用多项过载服务或多次调用单一过载服务的情况,作者在论文中专门创造了一个新的词汇,即“后续过载”。

“Subsequent overload raises challenges for effective overload control. Intuitively, performing load shedding at random when a service becomes overloaded can sustain the system with a saturated throughput. However, subsequent overload may greatly degrade system throughput beyond that intended…”(后续过载会对过载控制机制的有效性提出挑战。直观来讲,在服务过载时执行随机减裁操作可以将系统的实际吞吐量维持在饱和状态。而后续过载则可能大大降低超出预期的系统吞吐量……)

这里考虑一个简单的场景,其中服务A对服务B进行了两次调用。如果B开始对全部传入请求中的半数加以拒绝,则服务A的调用成功率将下降至0.25。

DAGOR概述

微信采用的过载控制系统被称为DAGOR,其旨在为所有服务提供过载控制功能,因此必须具有服务中立性。由于集中式全局协调将带来高昂的实现成本,因此过载控制需要以单一机器的细粒度方式运行。然而,其中还包含有处理后续过载情况所必需的轻量级机器间协调协议。最后,当由于严重过载而导致的减载变得不可避免时,DASGOR应尽可能维持服务的请求成功率。换言之,其应尽量减少浪费在失败服务任务上的计算资源(例如CPU与I/O等等)。

这里,我们有两项基本任务需要解决:检测过载情况,并在检测到过载之后决定如何加以处理。

过载检测

对于过载检测,DAGOR着眼于待处理队列中各请求的平均等待时间(或者说排队时间)。排队时间的最大优势,在于能够抵消呼叫图中较低延迟的平均化影响(相较于请求处理时间等指标)。即使本地服务器本身没有发生过载,请求处理时间也有可能增加。DAGOR可采用基于窗口的监控机制,其中的容器为1秒或者2000次请求,以先到者为准。微信显然一直处在高效紧张地的运行状态之中:

“For overload detection, given the default timeout of each service task being 500ms in WeChat, the threshold of the average request queuing time to indicate server overload is set to 20ms. Such empirical configurations have been applied in the WeChat business system for more than five years with its effectiveness proven by the system robustness with respect to WeChat business activities.”(对于过载检测,假设微信中每个服务任务的默认超时为500毫秒,则表示服务器过载的平均请求排队时间阈值将设置为20毫秒。这种基于经验的配置方式已经在微信业务系统中应用了超过五年之久,其有效性通过系统对微信业务活动支持的稳健性表现得到了证实。)

接纳控制

一旦检测到过载状况,我们就必须决定如何加以处理。或者更具体地讲,我们需要考量放弃哪些请求。这时,我们首先需要明确一点,各项请求之间并不是平等的:

“The operation log of WeChat shows that when WeChat Pay and Instant Messaging experience a similar period of service unavailability, user complaints against the WeChat Pay service are 100x those against the Instant Messaging service.”(微信的运营日志显示,每当与微信支付与即时消息体验相关的服务发生不可用问题时,用户对微信支付服务的投诉是针对即时消息收发服务的100倍。)

为了以服务中立性方式处理这个问题,每项请求在首次进入系统时都会被赋予一种业务优先级。这项优先级会随着所有下游请求一同继承。用户请求的业务优先级由其请求的操作类型决定。虽然存在数百个入口点,但实际其中只有几十个具有显性优先级,其它所有入口点都默认属于较低优先级。优先级设定保留在复制的哈希表当中。


图:用于存储微信入口服务内操作执行业务优先级的哈希表


当过载控制被设定为业务优先级n时,所有来自n+1等级的请求都将被放弃。这种方式对于混合型工作负载来说效果良好,但假定我们面对的是大量付款请求,而所有请求都具有相同的优先级(假定为p),那么一旦系统遭遇过载,我们就需要调整过载阈值以实现轻载,即将过载阈值变更为p-1。而一旦检测到轻载,过载阈值将再次增加至p,这时我们将重新面对过载状态。因此,要在大量具有相同优先级的请求引发超载时停止这种无意义的转换,我们需要采用超越业务优先级的细粒度调整。

微信对此拿出了一种良好的解决方案。其增加了基于用户ID的第二层接纳控制机制。

“User priority is dynamically generated by the entry service through a hash function that takes the user ID as an argument. Each entry service changes its hash function every hour. As a consequence, requests from the same user are likely to be assigned to the same user priority within one hour, but different user priorities across hours.”(用户优先级由入口服务通过以用户ID为参数的哈希函数动态生成。每项入口服务每小时变更一次其哈希函数,因此来自同一用户的请求很可能在一小时之内被分配予相同的用户优先级,但在数小时内被分配予不同的用户优先级。)

这就提供了公平性,同时亦能够在相对较长的时间周期内为个人用户提供一致的使用体验。另外,其还有助于解决后续过载问题,因为来自被分配予高优先级用户的请求更有可能在整体调用图中得到及时处理。

将业务优先级与用户优先级结合起来,即可为每个业务优先级提供配合128种用户优先级的复合接纳级别。


图:复合接纳级别


“With each admission level of business priority having 128 levels of user priority, the resulting number of compound admission levels is in the tens of thousands. Adjustment of the compound admission level is at the granule of user priority.”(由于每项业务优先级的接纳级别都包含128种用户优先级,因此其得出的复合接纳级别数量将达到数万种。对复合接纳级别的调整,能够细化至用户优先级粒度。)

另外值得一谈的是,为什么要采用用户ID而非会话ID来解决上述问题:因为如果以会话ID为解决方案,用户最终只会通过注销并重新登录的方式解决服务无影响问题,而由此带来的重新登录风暴将带来新的过载冲击!

DAGOR在每台服务器上都维持着一套关于请求的直方图,用于追踪超过接纳优先级的请求的大体分布情况。当在窗口期间检测到过载时,DAGOR会移动至另一“桶”(范围),这将使预期负载减少5%。而如果过载消失,其同样会移动至新的“桶”(范围),这将使预期负载增加1%.

服务器会在发送至上游服务器的每条响应消息中附带其当前接纳级别。通过这种方式,上游服务器将获知下游服务的当前接纳控制设置,甚至能够在发送之前即对该请求执行本地接纳控制操作。

因此,DAGOR的端到端过载控制系统将如下所示:



图:DAGOR过载控制工作流


实验

DAGOR设计有效性的最佳证明,在于其已经在微信的生产环境中拥有长达五年的良好运作记录。不过这无法为学术论文提供必要的图表,因此我们进行了一组模拟实验。下图突出显示了基于排队时间——而非响应时间——的过载控制成效。在后续过载的情况下,这种收益最为明显(如图(b)所示)。



与CoDel以及SEDA相比,在进行一次后续调用时,DAGOR凭借着后续过载机制使请求成功率提高了50%。后续请求数量越大,这种收益就越是明显:



图:不同工作负载类型下的过载控制


最后,在公平性方面,CoDel在高压场景下更倾向于使用扇出量较小的服务,而DAGOR则在各类请求当中表现出大致相同的成功率水平。



图:过载控制的公平性


构建处有系统中的三项经验


即使你不打算完全按照微信的方式使用DAGOR,作者仍然总结出了三项宝贵的实践经验:


•超大规模微服务架构下的过载控制必须在每项服务中实现分散与自治。


•过载控制应当考虑到各种反馈机制(例如DAGOR的协调接纳控制),而非仅仅依赖于开环启发式机制。


•应当通过对实际工作负载的处理行为进行分析,从而探索过载控制的设计思路。

(编辑:admin)
条记录

TOP

  • 娱乐淘金/
  • 行业/
  • 政策/
  • APP

资讯视频