默认
打赏 发表评论 6
想开发IM:买成品怕坑?租第3方怕贵?找开源自已撸?尽量别走弯路了... 找站长给点建议
微信后台团队:微信后台异步消息队列的优化升级实践分享
阅读(152829) | 评论(6 收藏8 淘帖2
微信扫一扫关注!

本文来自微信后台团队廖文鑫的技术分享。


1、引言


MQ 异步消息队列是微信后台自研的重要组件,广泛应用在各种业务场景中,为业务提供解耦、缓冲、异步化等能力。本文分享了该组件2.0版本的功能特点及优化实践,希望能为类似业务(比如移动端IM系统等)的消息队列设计提供一定的参考。

2、关于分享者


廖文鑫,2013年加入腾讯,从事微信后台基础功能及架构的开发和运营,先后参与了消息通知推送系统、任务队列组件、春晚摇红包活动等项目,在海量分布式高性能系统方面有丰富的经验。

3、背景介绍


微信后台给件 MQ 1.0 发布之初,基本满足了一般业务场景的异步化需求,实现了单机下高性能的任务持久化和消费调度。

MQ 1.0 的基本框架如下图所示:
微信后台团队:微信后台异步消息队列的优化升级实践分享_1.png

可以看到,其主要分为 MQ 和 Worker 两部分。MQ 是任务的持久化和调度框架,Worker 是任务的处理框架。

该组件与常见的队列相比,有几个特点:

  • 关注单机性能,任务单机持久化,本机消费;
  • 框架介入了任务的整个生命周期,其中包括了:入队落盘、派发、处理、提交结果、销毁。业务基于框架开发,专注任务的处理逻辑。

随着业务发展,面对日益复杂的业务场景,1.0 版本逐渐显得力不从心。因此,在 1.0 的基础上,我们实现了 MQ 2.0 版本,主要优化点包括以下几方面:

  • 更优的任务调度;
  • 更高效的任务处理;
  • 更强的过载保护。

下面对各个优化点详细讲解。

4、需要实现更优的任务调度


4.1现状分析


iOS消息通知功能,是MQ组件的一个典型应用场景。微信的后台具有多IDC分布的特点,不同IDC与苹果推送服务(APNs)之间的网络质量参差不齐,部分链路故障频发。

微信后台团队:微信后台异步消息队列的优化升级实践分享_2.png

由于MQ 1.0 的任务只能本机消费,网络质量的下降将直接导致 Worker 消费能力的下降,进而产生积压,最终使消息服务质量受损。

为此,我们提出了跨机消费模式。其目标是实现一个去中心化、自适应的弹性消费网络,以解决系统中出现的局部积压问题。

4.2任务调度是跨机消费的核心问题


消费模式从单机扩展到多机后,我们要面临的核心问题是,哪些任务给哪个 Worker 去处理。其实,考虑多机房、多IDC、带宽成本、任务延时等因素,我们很容易得到一个直观而朴素的思想:任务优先在本机消费,产生积压时才发生跨机消费

如何实现我们想要的跨机消费呢?经过思考,我们将问题分解为三个子问题:

  • 拉任务还是推任务?
  • Worker 如何感知 MQ 的积压?
  • Worker 如何消除 MQ 的积压?

下面逐一进行讨论。

4.3拉任务还是推任务


MQ 1.0 下,MQ 可以准确观察到本机 Worker 的负载状态,并由其将任务推送给空闲的 Worker 进行处理。推送的方式可以将任务的处理延时做到极低。

扩展到跨机消费后,Worker 可以消费任意 MQ 的任务。对 MQ 而言,已经难以精确地维护全网每个 Worker 的状态了。若继续沿用推任务的方式,很可能会出现 Worker 接收到超过其处理能力的任务量,从而产生积压。

若使用 Worker 拉取任务的方式,则拉取的速度可以根据 Worker 自身的消费能力调整,但在任务延时上,需要有所牺牲。

推任务:优点,低延时;缺点,任务在 Worker 端积压,无法被重新调度;
拉任务:优点,任务在 MQ 端积压,可以被空闲的 Worker 拉走;缺点,延时稍高。

经过简单的权衡,我们选用了拉任务的方式,毕竟,我们难以接受任务积压在 Worker 侧的情况。

4.4Worker 如何感知 MQ 的积压


前面提到,系统应该在任务出现积压时,才产生跨机消费。因此,MQ 在产生积压时,应该要能以某种形式通知 Worker。

同时,积压量的变化是很快的,通知的方式应该做到以下几方面的高效:

  • 速度:尽可能地快;
  • 精度:尽可能少地发送通知,减少无效通知的发送。

为此,我们实现了广播模式,将 MQ 产生的积压量信息作为一个消息,广播给 多个Worker。

微信后台团队:微信后台异步消息队列的优化升级实践分享_3.png

它在实现上如何满足高效的积压通知要求呢?

  • 速度:使用长连接将积压量信息推送到 Worker 端;
  • 精度:通过灵活的订阅过滤器,实现对本机、跨机、跨IDC的分级的广播。

通过广播模式,我们高效地解决了 MQ 积压的感知问题。

4.5Worker 如何消除 MQ 的积压


通过广播模式,每个Worker 都可以观察到所有它感兴趣的 MQ 的积压情况,并以此构建出整个系统的积压分布统计。拿到这些信息后,Worker 如何决定拉取哪个 MQ 的任务呢?

还是回到我们的原始诉求,尽量做到本机消费。所以我们的策略是说,Worker 应该优先消除本机的积压,当它有余力的时候,才去帮助其它Worker。

微信后台团队:微信后台异步消息队列的优化升级实践分享_4.png

通过分优先级地拉取,既可在队列系统正常时大量降低跨机消费,同时也可以在故障发生时,有效地消除局部积压。

4.6负载均衡分析


跨机消费模式,从整个系统角度来看,是完全去中心化的,任意一个 MQ 和 Worker 个体都可以独立、自由地加入或退出系统。

微信后台团队:微信后台异步消息队列的优化升级实践分享_5.png

在这个竞争式的消费系统里,根据具体的部署情况、不同机型消费能力不同等因素,无法达到完全的负载均衡状态。但在系统产生局部过载时,则可以自适应调节,达到相对的均衡。

4.7小结


从实际应用效果来看,MQ 2.0实现了通知推送服务的IDC级别容灾,即使只剩下一个IDC可用,也可以做到推送质量纹丝不动。

MQ 2.0 对跨机消费模式的支持,为业务提供了一种新的队列容灾模式:

  • MQ 与 Worker 可完全分离部署,分别规划机器数量,按需部署,互不影响;
  • MQ 的局部积压可以通过扩容 Worker进行消除;
  • Worker 的局部消费能力下降可以由其它 Worker 自动容灾。

5、需要实现更高效的任务处理


5.1现状分析


微信发布已有6年多的时间,后台的业务逻辑演化至今,往往是非常的复杂,我们来看一个比较极端的例子 —— 群聊批量并行化投递

微信后台团队:微信后台异步消息队列的优化升级实践分享_6.png

上图是群消息投递业务的简化流程示意。随着微信群消息体量的高速膨胀,其带来的成本压力越来越大,业务同学提出了批量并行化的优化方式。简单来说,就是将每个步骤中产生的 RPC 访问按实际访问机器聚合成一系列的批量操作,然后并行化执行。

通常来说,单次的批量并行化并不难写,一般而言,业务同学可能会选择裸写。但如果涉及多次的批量并行化,其中还存在嵌套的话,事情就不那么简单了。最终代码将变得异常复杂,业务开发的同学苦不堪言。MQ 能否从框架上解决这类问题?

5.2类 MapReduce 任务处理框架


其实,深入分析群消息投递的优化需求,可以看到:

  • 一次批量并行化操作本质上是一次 MapReduce 过程;
  • 整个群消息投递的处理过程是多次 MapReduce 过程的串联和并联。

所以,为了从根本上解决这一类问题,MQ 为业务提供了类 MapReduce 任务处理框架。

微信后台团队:微信后台异步消息队列的优化升级实践分享_7.png

该框架提供封装了通用的 MapReduce 过程,以及并发的调度过程,同时提供并发池隔离能力,解决了并发池饿死的问题。让业务同学可以从冗繁的代码中解放出来,将更多的精力投入到实际业务中。

5.3流式任务处理框架


除了批量并行化的需求,业务经常提到的一个需求是,任务处理时会产生一些新的任务需要加到队列中。一般来说是走一次 RPC 来执行任务入队。在 MQ 2.0 下,流式任务可以帮忙完成这个事情。

所谓流式任务,就是在任务处理结束时,除了返回任务结果,还可以返回一系列新的任务。这些任务通过 MQ 内部框架流转入队,更轻量,事务性更强。

微信后台团队:微信后台异步消息队列的优化升级实践分享_8.png

相比常规的同步处理模型,它提供了一种轻量的逻辑异步化模型。一个冗长的逻辑可以切分为很多小的功能块进行串联和复用,每一级之间都有 MQ 去充当缓冲和调度。虽然这种处理模式并不适用于所有逻辑,但作为组件功能的一部分,它提供了一种新的解决问题的能力。

5.4小结


MQ 2.0 提供的类 MapReduce任务处理框架和流式任务处理框架,为业务的实现提供了便利的支持。

6、需要实现更强的过载保护


6.1现状分析


MQ的重要作用是充当系统中的缓冲节点,流量控制的能力是非常关键的。在 MQ 1.0 下,只能通过配置队列的任务出队速度来实现流量控制。

其问题有几个:

  • 配置需要人工调整,难以估算对后端的实际访问;
  • 后端处于过载状态时无法自适应调整;
  • 自己处于过载状态时无法自适应调整。

6.2问题分析


从需求来看,MQ 的过载保护需求有两个方面,一是保护自己不过载,二是保护后端不过载。

导致过载的因素很多,从 MQ 的角度来看,这些因素可以分为两大类。一种是它能直接观察的因素,如自身的 CPU 使用率,内存使用率,任务执行的成功率;另一种是无法直接观察的因素,如业务实际对后端产生的调用量。

从这两类因素出发,我们将过载保护的策略分为两大策略:

  • 前向限速:MQ 通过其直接观察到的数据,主动对任务派发进行限速;
  • 后向限速:MQ 通过业务反馈的数据,被动对任务派发进行限速。

下面分别讨论两种策略。

6.3前向限速


基于 CPU 使用率的流控:
该限速策略很好理解,就是在 CPU 使用率过高时,降低任务处理速度,以将 CPU 资源优先用于保证队列的缓存能力。
微信后台团队:微信后台异步消息队列的优化升级实践分享_2.png

基于任务成功率的流控:
后端模块故障时,往往会导致队列任务出现大量的失败和重试,这些重试的量级往往会远超该后端模块设计的有效输出,给故障恢复带来很大的困难。该流控策略的通过收集任务执行的成功率信息,评估后端的有效输出,并通过反馈计算限制任务重试的速度。
微信后台团队:微信后台异步消息队列的优化升级实践分享_10.jpeg

6.4后向限速


MQ 实现了通用的后向限速能力,业务通过特定接口往 MQ 回传控制量,达到速度调控的目的。

基于后端 RPC 访问量的流控:
我们经常会遇到一些业务在处理任务时,存在不同程度的对后端的扩散访问。仅对任务处理速度进行限制,无法准确限制对后端产生的实际调用量。该策略通过收集业务对后端产生的实际调用量,反向调节任务处理的速度。
微信后台团队:微信后台异步消息队列的优化升级实践分享_11.jpeg

6.5小结


MQ 2.0 通过分析流控需求,在前向和后向分别提供了有效的流控手段,并且为后续更精细的流控策略预留了拓展的能力,增强了过载保护的能力。

7、本文总结


微信的队列组件,与业界其他队列相比,其突出的特点是更贴近实际业务场景,极大地解放了业务同学的生产力。

MQ 2.0 在 1.0 的基础上,在任务调度、任务处理、过载保护这几方面做了大量的工作和尝试,目前已在微信各个核心业务模块运行,并经历了2017年除夕流量洪峰的考验。

后续,将在任务持久化容灾和调度性能上,对该组件进行持续的优化。

(原文链接:点此进入

附录:相关文章汇总


[1] 有关QQ、微信的技术文章:
微信后台团队:微信后台异步消息队列的优化升级实践分享
微信团队原创分享:微信客户端SQLite数据库损坏修复实践
腾讯原创分享(一):如何大幅提升移动网络下手机QQ的图片传输速度和成功率
腾讯原创分享(二):如何大幅压缩移动网络下APP的流量消耗(下篇)
腾讯原创分享(二):如何大幅压缩移动网络下APP的流量消耗(上篇)
微信Mars:微信内部正在使用的网络层封装库,即将开源
如约而至:微信自用的移动端IM网络层跨平台组件库Mars已正式开源
开源libco库:单机千万连接、支撑微信8亿用户的后台框架基石 [源码下载]
微信新一代通信安全解决方案:基于TLS1.3的MMTLS详解
微信团队原创分享:Android版微信后台保活实战分享(进程保活篇)
微信团队原创分享:Android版微信后台保活实战分享(网络保活篇)
Android版微信从300KB到30MB的技术演进(PPT讲稿) [附件下载]
微信团队原创分享:Android版微信从300KB到30MB的技术演进
微信技术总监谈架构:微信之道——大道至简(演讲全文)
微信技术总监谈架构:微信之道——大道至简(PPT讲稿) [附件下载]
如何解读《微信技术总监谈架构:微信之道——大道至简》
微信海量用户背后的后台系统存储架构(视频+PPT) [附件下载]
微信异步化改造实践:8亿月活、单机千万连接背后的后台解决方案
微信朋友圈海量技术之道PPT [附件下载]
微信对网络影响的技术试验及分析(论文全文)
一份微信后台技术架构的总结性笔记
架构之道:3个程序员成就微信朋友圈日均10亿发布量[有视频]
快速裂变:见证微信强大后台架构从0到1的演进历程(一)
快速裂变:见证微信强大后台架构从0到1的演进历程(二)
微信团队原创分享:Android内存泄漏监控和优化技巧总结
全面总结iOS版微信升级iOS9遇到的各种“坑”
微信团队原创资源混淆工具:让你的APK立减1M
微信团队原创Android资源混淆工具:AndResGuard [有源码]
Android版微信安装包“减肥”实战记录
iOS版微信安装包“减肥”实战记录
移动端IM实践:iOS版微信界面卡顿监测方案
微信“红包照片”背后的技术难题
移动端IM实践:iOS版微信小视频功能技术方案实录
移动端IM实践:Android版微信如何大幅提升交互性能(一)
移动端IM实践:Android版微信如何大幅提升交互性能(二)
移动端IM实践:实现Android版微信的智能心跳机制
移动端IM实践:WhatsApp、Line、微信的心跳策略分析
移动端IM实践:谷歌消息推送服务(GCM)研究(来自微信)
移动端IM实践:iOS版微信的多设备字体适配方案探讨
>> 更多同类文章 ……

[2] 有关QQ、微信的技术故事:
技术往事:创业初期的腾讯——16年前的冬天,谁动了马化腾的代码
技术往事:史上最全QQ图标变迁过程,追寻IM巨人的演进历史
开发往事:深度讲述2010到2015,微信一路风雨的背后
开发往事:微信千年不变的那张闪屏图片的由来
开发往事:记录微信3.0版背后的故事(距微信1.0发布9个月时)
一个微信实习生自述:我眼中的微信开发团队
>> 更多同类文章 ……

即时通讯网 - 即时通讯开发者社区! 来源: - 即时通讯开发者社区!

标签:微信 IM群聊
上一篇:移动端IM登录时拉取数据如何作到省流量?下一篇:通俗易懂:基于集群的移动端IM接入层负载均衡方案分享

本帖已收录至以下技术专辑

推荐方案
评论 6
文章写的有深度,没有相应经验的im开发是看不太懂的
签名: 国庆长假还没有缓过来,请让我静一静,产品狗死远点...
多谢分享
厉害了
学习了
签名: 今天天气不错,写的真好
还是很开眼界的。大厂都定制自己的基础组件
签名: now start 。。。
引用:妮子 发表于 2019-12-16 14:37
还是很开眼界的。大厂都定制自己的基础组件

那肯定的
打赏楼主 ×
使用微信打赏! 使用支付宝打赏!

返回顶部