微信与服务器中间,庞大用户量,每秒数亿请求,微信服务器如何做到不“失控”?...

最近我读了一篇论文《Overload control for scaling WeChat microservices(用于扩展微信微服务的过载控制)》,十分喜欢。

这篇论文主要分两部分:首先,我们能了解一些微信后台的内部消息;其次,作者分享了一种经过实践检验的过载控制系统DAGOR,该系统已经在微信上运行了五年。友情提示,这个系统在设计时就考虑了微服务架构的特殊情况,所以如果你想在自己的微服务上采用某种策略,那最好还是以这个系统为起点参考。

1.每秒需要处理几亿请求的微信后台

现在的微信后台由3000多个移动服务构成,包括实时消息、社交网络、移动支付和第三方认证等,平台每天能处理大约1010~1011外部请求。每个请求可能触发更多的内部请求,所以微信的后台作为一个整体,需要每秒处理大约几亿个请求。

微信将微服务分类为“入口层”服务(接收外部请求的前端服务)、“共享层”服务(中间层协调服务)和“基本服务”(不调用其他服务的服务,请求在这里终结)。

042c8bd1a4f80e3926011f1bfecd056a.png

图1 微信的微服务架构

每天,峰值请求大约是日平均请求的三倍。在每一年的固定时期(例如在中国的新年前后),峰值负载可能达到日平均负载的10倍。

2.基于微服务的大型平台过载控制的难点

传统的过载控制机制主要用于只有少量服务组件的情况,通常包括一个较窄的“前门”,加上一些不重要的依赖。

发送到微信后台的请求没有单一的入口点,而传统方式是在全局入口点(网关)上以中心化的负载监视为主,因此无法使用。

特定请求的服务调用图可能依赖于请求自身的数据和服务参数,甚至同一种请求的调用图都可能不同。所以,当特定服务出现过载时,很难确定应该拒绝哪一种请求来缓解压力。

过度的请求拒绝(特别是在调用图深处或者请求处理后期拒绝)会浪费大量计算资源,而且会由于高延迟而影响用户体验。

由于服务的调用图非常复杂,而且在不断变化,有效的跨服务协调的维护成本和系统额外开销非常高。

由于一个服务可能向它依赖的服务发出多个请求,还可能给多个后台服务发出请求,所以在处理过载控制时必须谨慎。作者采用了“序列过载”来描述多于一个过载服务被调用的情况,或一个过载服务被调用多次的情况。

考虑一个简单的情况,服务A调用服务B两次。如果B拒绝掉一半的请求,那么A的成功率就会下降到0.25。

3.微信的过载控制系统DAGOR

微信的过载控制系统叫做DAGOR,它的目标是给所有服务提供过载控制,因此被设计成与服务无关。过载控制运行在单个服务器的粒度上,因为中心化的全局协调太昂贵了。但是,它能够与轻量级的服务器间合作协议配合使用,后者在处理序列过载的情况时是必须的。最后,DAGOR应当在load shedding不可避免时尽可能维持服务的成功率。消耗在失败的任务上的计算资源(如CPU、I/O等)应当保持最小。

我们要解决两个最基本的任务:检测过载状况,决定检测到过载后的对策。

过载检测

对于过载检测,DAGOR采用了等待队列请求平均等待时间(即排队时间)。排队时间可以有效地避免调用图中的延迟造成的影响(可以与其他指标比较一下,比如请求处理时间等)。即使过载没有发生,本地服务器上的服务处理时间也可能增加。DAGOR基于窗口进行监视,窗口大小为1秒或2000个请求,先到者为准。显然,微信做得不错:

任务控制

检测到过载后,我们要决定怎样处理过载。或者更直接地说,要确定拒绝哪些请求。首先我们注意到并非所有请求都是平等的:

为了以服务无关的方式来处理,每个请求在进入系统时都要指定业务优先级,这个优先级会流向下游的所有请求。用户请求的业务优先级由被请求的操作类型决定。尽管有几百个入口点,但只有几十个入口点有明示的优先级,其他的均为默认优先级(较低的优先级)。优先级用一个有副本的哈希表来维护。

ab2a875ac71780bb475b193c9481ed49.png

图2 哈希表存储了微信的各个入口服务进行操作的业务优先级

当过载控制被设置为业务优先级n时,所有n+1以上的请求都会被拒绝。对于混合型的负载,这种策略非常好用。但如果出现大量支付请求,所有请求的优先级都相同(均为p),那么系统就会过载,于是就会把过载阈值设置为p-1,从而使负载降低。一旦检测到负载降低,就会把过载阈值再设置为p,从而又导致过载。为了避免这种由大量优先级相同的请求导致的反复情况,我们需要比业务优先级更细粒度的控制。

微信的解决方案很巧妙,它根据用户ID增加了另一层控制。

这样能保证公平,同时为每个用户在相对长的一段时间内提供一致的用户体验。这样做还能帮助控制序列过载问题,因为来自同一个用户优先级更高的请求高更容易在整个调用图中畅通无阻。

将业务优先级和用户优先级结合使用,能够在每个业务优先级内提供128级的用户优先级。

b6f8268a83ba9ad456f8f1d99e57b79c.png

图3 组合优先级

为什么一定要使用用户ID而不能使用会话ID呢?因为后者会让用户养成在服务差的时候重新登录的习惯,进而会导致在原来的过载问题上出现大量的登录!

DAGOR在每个服务器上维持一个直方图,来跟踪各个优先级的请求的大致分布情况。当在某个窗口内检测到过载时,DAGOR移动到第一个桶,将预期的负载减小5%。如果没有负载,就会到第一个桶内,将预期负载增加1%。

服务器还会顺便将每个响应消息的当前优先级发送到上游服务器。这样,上游服务器就能知道当前下游服务的控制设置,从而甚至可以在发送请求之前进行本地控制。

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

17eae4ea0bba3e467e90e57b2ab09167.png

图4 DAGOR过载控制系统的工作流

实验

DAGOR设计的最佳实证就是它已经在微信的产品环境里运行了五年之久。但对于学术论文来说这还不够,因此作者还提供了一系列模拟实验。下面的几张图显示了基于排队时间的过载控制要比基于响应时间的好得多。优势主要出现在系列过载的情况下(图(b))。

08157893691d5a6ff12ce4c1a9c1118d.png

图6 利用不同的负载评测指标进行过载检测:排队时间 vs. 响应时间

与CoDel、SEDA相比,在系列过载的情况下,发送一个系列调用时DAGOR的请求成功率要高出50%。系列请求的数目越高,优势就越大。

b7d1ba5184a99a071ea2b7b9d23812b3.png

图5 不同类型负载下的过载控制

最后为公平起见,可以看出CoDel更适合扇出较小的服务,而DAGOR能在多种不同请求的情况下达到同样的成功率。

38edbf73272ad5b1045103bc4efbc325.png

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值