钉钉 IM 的 RocketMQ 应用实践 | 学习笔记

简介: 快速学习钉钉 IM 的 RocketMQ 应用实践

开发者学堂课程【2022阿里云云原生中间件开发者大会集锦钉钉 IM 的 RocketMQ 应用实践学习笔记,与课程紧密连接,让用户快速学习知识。

课程地址https://developer.aliyun.com/learning/course/1053/detail/15300


钉钉 IM 的 RocketMQ 应用实践


内容介绍

一、钉钉 IM 的介绍

二、产品的对传统漏洞的升级

三、选择原因

四、消息必达流程介绍

五、分布定时任务的开始

六、使用过程遇到的问题

七、升级模式


一、钉钉 IM 的介绍

最近几年钉钉的RocketMQ最近几年迅速成为国民级的应用,不仅支持海量用户的企业级沟通还通过pass的形式并为淘宝、高德等APP提供了基础的即时通讯能力,是一个日均千亿级消息量的im平台。这次给大家分享rocket mq在系统中的应用实践,不仅利用RocketMQ实现了系统的解耦异步化削峰填谷,还通过定时消息实现了分布式定时任务的高级特性。另外在使用RocketMQ过程中,也和RocketMQ的开发深入共创,不断优化,解决了很多问题,并且孵化出poem消费模式等新特性,让RocketMQ能非常好的知识,对性能稳定性直言要求非常高的im系统钉钉作为企业级的领先者。

二、产品的对传统漏洞的升级

(1)产品面临的问题

面临的技术挑战非常大,首先作为一个企业级应用,需要保证交付给用户,能帮用户提升沟通体验,to b的工作沟通和to c场景的生活沟通具有较大的差异。

To c产品比如微信在有了完整的关系链之后,只需要满足大部分用户的需求就好出一个简单的打飞机,跳一跳都能成为全国爆款,但是他们很多地方的体验其实并不好,比如说是他们微信的视频图片消息,几天没看就无法下载卸载,重装之后聊天记录就全部丢失的。而to b场景的聊天记录非常重要。

image.png

(2)钉钉的升级能力

钉钉为了保证用户的消息不丢,提供了多端同步和消息云端存储的能力,让大家不管怎么换端都有一次性的体验。

在工作过程中,常常因为沟通效率问题,开会大量的会议又是工作效率的杀手,提供了以钉钉效力套件等为大家的工作沟通提供了一个新的选项。

其次工作场景下用户对信息安全的要求非常高,是企业的生命线,提供了和组织架构打通的工作群,用户在离开组织会自动退出企业的工作群,很好的保障了企业的信息安全。

同时在钉钉官方已经支持了全电路加密的能力上,还提供三方加密的能力,最大程度保障企业用户的信息的安全性。在稳定性这一块,企业及用户要求非常高,如果钉钉出现故障,那么深度使用钉钉的企业的的正常运转都会受到影响,是和企业的合同也对稳定性是有明确要求的。 整个im系统在稳定性上面也做了非常深入的建设,架构上对依赖和流量做了深入治理,核心能力的所有依赖都有双倍。

比如说后面讲到的,虽然RocketMQ已经非常稳定,也没给带来过故障,但是对RocketMQ可能出现的故障产品做了很好的保护,也使用了RocketMQ的定时消息和堆积能力,做了热点治理和流量防护,让整个系统面对大规模流量时能从容应对,并且建设了异地多国和可弹性扩输入能力。

(3)实际情况举例

在疫情期间很好的保证学生们的在线课堂在2020年大量学生分期给了第一颗星,新的评分给钉钉,希望他们能走路,早日把分期的五星付给钉钉,同时在稳定性机制上常态化的容灾演练、突袭演练、自动化健康巡检,显也能很好的保证线上的稳定性。 后面提到的问题,比如说波浪式流量,就是在做断网演练时发现的,最后因为不同行业的多样性,很难用一套解决方案满足所有企业的诉求,通用性如超大群钉钉官方费实现更多的会将im能力通过open API的形式,尽可能的开放给企业和三方isv做过市场调研,今天im开放的能力是行业里面最多的,集合业界的智慧,把钉钉的生态打造好。

在上述如此丰富的企业级能力的情况下,要和微信这种to c产品一样,支持一级用户的第一时间沟通,系统上架构上具备高并发、高性能高可用能力,面临的挑战非常大。

(4)im 异步化沟通系统作用与发送流程

Im本身是一个异步化沟通系统,它与开会或者电话沟通相比,能够让沟通的双方异步处理消息,减少打断次次数,提升大家的专注时间,这种异步的特性和消息队列的能力很契合,消息队列可以很好的帮助im完成异步化解耦失败,从事削等能力,这里我给大家选取整个im系统最核心的发胸芯和已读电路的简化流程,给大家讲一下消息队列在系统里的重要作用。

首先来看发消息流程,一个钉钉用户处于登录状态,发送一条消息时,首先会把请求发送到这个叫reserve的应用上。

为了保证发消息的体验和成功率,这个应用只做这条消息能不能发送的校验,其他如消息入库,接收者推送交给下游的应用去做,他校验成功之后把消息投递给消息队列,也成功之后就可以返回给用户。

这条消息发送成功,接着process会从消息堆页里面订阅到这条消息,并对消息进行入库,处理处理成功之后,通过我消息队列把这条消息交给的同步服务,think社会去做处理think so。

image.png

这个应用把消息同步给在线的接收者,对于不在线的用户可以通过消息队列也把消息推给离线系统离线谱曲系统可以对接苹果的apns华为小米等推送系统进行离线推送,在用户发消息成功之后,每一步如果失败都可以通过消息队列进行从事处理,如processor这里入库失败的话,可以把消息扔回消息队列,然后继续回旋处理,达到最终一致。

接下来看以不链路用当一个用户对一条消息做了读操作之后,会发请求到以读服务以读服务收到请求之后,然后直接把请求放到消息队列进行异步处理,异步处理的同时还可以达到削峰填谷的目的,以毒服务处理完之后,就把以读这个事件推给同步服务,我让同步服务,把对方已读的这个事件推送给消息的发送者,这样子消息的发送者就能看到这条消息,对方已经读过。


三、选择原因

image.png

从上面两个链路看,消息队列是整个im系统里面非常重要的组成部分,刚刚我介绍了im系统里销售队列非常重要,接下来给大家介绍一下为什么选用RocketMQ,大家可能会问阿里的系统选用RocketMQ不是很自然的事情,其实阿里内部曾经也有RocketMQ两套广泛应用的消息中间,件也也有其他基于基于mq TT协议实现的消息队列,最新都被落给了mq统一了。

来先看一下m系统对消息队列的基本要求,首先是解耦和削峰填谷,这两个都是消息队列的基础能力。除此之外,m系统对高性能低时延的要求也非常高,同时在可用性上要求也非常高不仅是,对系统的可用性研究也有数据的可用性,写入消息队列的消息能保证不丢失。 钉钉im对消息的保障级别是一条都不能丢,而若k的mq经过了多次双11的考验,它的堆积能力性能低,时延高可用,已经成为了业绩的标杆,符合对消息队列的要求。

同时它的一些其他的特性也非常丰富,如定时消息、事物、消息,让很低成本就实现了一个分布式的定时任务,消息的可重放和死刑队列,也让有后悔药吃。比如说当的线上的系统出现了bug,很多消息没有正确处理,还可以通过重置位点重新消费的方式,把之前的错误处理给订正回来。

另外用到消息队列的场景非常多,罗平来mq的扩展能力,也让在消息的发送和消费的地方可以做一个切面处理,实现一些通用性的扩展封装,大大降低的开发工作量, tag和c口过滤也能让的下游能针对性的订阅对应业务需要的消息,而不是订阅整个topic和里面的所有消息,大大降低了下游系统的订阅压力。

这是钉钉,RocketMQ使用情况,在可用性上至今没有 RocketMQ引发的故障性能上上集群的峰值TPS达到过300万每秒,时延上从生产到消费,10年一直保证在10毫秒以内堆积上也支持过31条消消息的堆积,整个RocketMQ的核心指标数据都非常抢眼,表现的非常优秀。

image.png

 

四、消息必达流程介绍

接下来给介绍钉钉是如何做到消息必达的,前面给大家介绍了一下发消息流程,其中很重要的一步是 receive这个应用在做完这条消息能不能发的校验之后,通过洛克兰把消息投递给process做消息的入库处理。

image.png

看这个图在投递过程中的话,有三保险,首先第一重保险是RocketMQ,把消息 VC把消息写进RocketMQ其实RocketMQ的SDK默认会从事5次尝试写入RocketMQ就本身这种写入失败的概率非常小,这种非常小概率出现的场景的话,也有有其他两个保险,保险二的话是在写入说给他们q失败的情况下,会尝试rpc的形式把消息投递给process。 如果rpc的形式也失败的情况下,会尝试打本地的维度log,然后通过一个roundtable任务定时把消息回放到RocketMQ里面,做到消息的万无一失。

接下来看右边这个图,是如何在异系统异常的情况下做到消息的最终一致,processor在收到上游投递过来的消息时,会尝试对消息做入库处理,在入库失败的情况下,还是会把消息投给同步服务,对消息进行下发,保证实时消息的收发异常,但是异常情况和正常情况有个不同的处理,就是会把消息重新投递到一个异常的topic进行从事投递的过程中,会通过设置RocketMQ的定时消息做做退避处理,在消费这个异常RocketMQ的时候做限速消费。 这里有两个问题可以大家可以思考一下。

第一个问题是是从事为什么要写新的topic,因为不是在现场,我这里就直接把答案揭晓,因为从事写不同的topic是为了跟正常流量隔离,优先处理正常流量,防止因为异常流量的消费而导致真正线上的这种消息的处理被延迟。另外的话就是RocketMQ的一个博客,默认只有一个Richard消息队列这样子,只是RocketMQ比较少,就会导致如果消费失败的量特别大的情况,下下游就会负债不均,然后把下游的某几台机器打死的情况。然后第二个问题是为什么要限速?限速的目的可以看到就是因为它会如果系统持续发生异常,它就会不断的去回旋从事,如果不做限速处理的话,就会很容易导致线上出现这种流量叠加,导致整个系统进入一个雪崩的状态。


五、分布定时任务的开始

接下来给大家看一下是RocketMQ实现分布式定时任务的开始,这个图所示,

image.png

在一个几千人的群里面发了一条消息,假如说这个时候有1/4的人同时开着这个聊天窗口,那么服务端的已读服务和我的客户端端需要更新这个维与毒素,如果不做合并处理的话,那我更新的QS要达到1000每秒,钉钉的超大群甚至支持几万甚至是十几万人群。

历史上这些超大群活跃起来,对的服务端客户端都会带来很大的冲击。 男孩实际上用户的需求秒级更新就可以了。

针对这种场景,利用RocketMQ的定时消息能力,实现了分布式定时任务如图所示,当一一个用户发起请求时,会把这些请求放到一个集中式的请求队列里,放入成功之后,通过RocketMQ的定时消息生成一个定时任务,比如说5秒之后噢,批量处理,5秒之后,从逻辑技mq就订阅到任务触发的消息起之后,把请求从请求队列里面把队列里面的所有请求都捞出来,处理,这里面讲的例子是已读,实际上抽象了一个分布式定时任务组件,有很多其他实时性要求可以到秒级的功能,如万人群的群状状态更新,消息扩展更新,都介入了这个组件,通过这个组件的的定时合并处理,大大降低了整个系统的压力。

如这个图里面可以看到,在一些大群活跃的时间点,成功的让整体的流量量降下来,并且保持一个很平稳的状态。

image.png

在使用RocketMQ的过程中也遇到了一些问题,先跟大家介绍一下rock的消息生产和消费模式,生产端的策略是生产者会拿到对应topic的所有的block和消息q的列表,然后允许写入消息。

消费者这一端的话是也是拿到这个 topic的对应的所有的RocketMQ的列表,另外的话还要从blog拿到所有消费者的IP列表进行排序,然后按照配置的负债均衡,如希一次性希同机房等策略算出自己应该订阅哪些q。


六、使用过程遇到的问题

首先第一个遇到的问题,就是波浪式的流量什么意思,就是之前发现就是订阅消息的集群滚动式CPU标高,比如说consumer1 CPU标标完之后很快降下来,接下来consumer2的CPU又标识上来。

当时很费解,后面经过深入的排查,发现是在晚上断网演练之后,网络进行恢复的时候,大量的的producer同时恢复工作。

然后他们都是同时从第一个博客的第一个q开始写入消息,这样子生产的消息就这样子波浪式的写入RocketMQ,进而导致的消费者也出现波浪式流量的情况,这个问题面通过随机选取初始q的方式解决了另外一个波浪式流量的问题,是自己的一个配置的问题。之前我排查过一个线上的问题,就是从broke视角看,每个broke的消息量都是平均的,但是的consumer之间流量相差特别大,在线上尝试添加了很多监控进行排查,都没有发现问题,后来到producer这一侧尝试抓包才最终定位问题,发现的producer写入消息的时候,超时率偏高,后来梳理配置发现是因为produce在写入消息的时候,配置的超时太短了,配置成两毫秒,然后mq在写消息的时候,他会尝试多次,比如说尝试broke第一个break,写入失败的时候,他会直接跳到下一个的第一个q这样子就导致每一个的第一个q消息量特别大,他靠后的一些party群几乎都没有什么消息。

第二个问题是负载均衡只能到爬T恤,只能到q维度,这就导致了要时不时关注 q的数量,线上就会出现过过流量增长的很快的情况,然后进行扩容,扩容的时候,发现扩出来的机器数大于整个q的数量,然后这样子就导致再怎么扩容都无法分担这些线上的流量,只能联系RocketMQ的运维同学帮忙调高到q的数数量,解决虽然调高q的数量能解决有的消有的机器无法订阅的问题,但是因为整个负载均衡的策略,直到q的维度都负载死,终会有不均的情况,从图里面这里就能很明显看到,比如说这一个consumer一订阅了两个q而consumer二只订阅了一个q,第三个问题就是单机夯实导致的消息堆积,这个问题也是负载均衡只能到 q维度带来的一些副作用。

用因为这些q比如说RocketMQ一是consumer一去订阅,线上之间就出现了宿主机的磁盘io夯实,但是他和broker之间的那个心跳还属于正常,那就导致是他订阅的这些q的消息都长时间无法订阅,进而影响的用户。出现收消息一直收不到的情况,直到手动记录把对应的机器下线才解决。第四个就是是rebels,因为broker mq的负载均衡是自己计算,这就导致有机器异常,或者是发布的时候,整个集群的状态不是很稳定,并时常会出现有的q就有多个同学们在订阅,有的q在在几十秒级别没有同学们订阅的情况,这样子就会让线上发布的时候,有用户就会感知到怎么我的消息乱序了,或者是对方回路我的消息。


七、升级模式

最后一个问题就是是的核心的刚刚提到的VC,不是s是不是那些应用都是c加实现的Mq的c++ SDK相比Java的话有较大的缺失,在一些容灾场景经常出现内存泄漏或者是CPU标高的情况,上面提到的这些问题的话,也困扰了有一段时间和罗体的mq的开发进行过多次的讨论和共创,最后孵化出罗体的mq5.0里面的pop消费模式。

image.png

从我的视角来看的话,这是RocketMQ在实时系统里面的一个一里程碑式的升级,它的升级解决了大量实时系统使用RocketMQ过程中遇到的问题,首先是重名轻端的模式,和老的模式相比,负载均衡订阅关系位点维护都是在客户端维护,而新的客户端只需要做长链接的管理消息的接收,并且使用通用的grpc协议这样子多语言,比如说c++等语言的客户端能很简单的实现,无需持续投入投入能力去升级维护SDK。

另外重云轻端的情况能很好的解决客户端版本升级的问题,在客户端做清之后,整个改动的可能性和频率大大降低,以往升级一个新特性或能力,只能推动所有的用到这个 SDK的应用进行升级发布,升级过程中还要考虑这种新老兼容,从整个的工作量扩散得非常厉害,而新的模式只需要升级broken就行了。

另外在新的模式下,这里的consumer\broke进行网状的连接和消息订阅由broke通过负载均衡策略平均分配消息给consumer进行消费,这样以往档期夯实导致对应q消息堆积的问题就是迎刃而解。 另外broke发现这台长时间没有进行消息的话,也可以不再投递给他上面提到的这种q的数量的问题,一般认识导致订阅延时抖动的问题全部都迎刃而解。

到前面说到的这种波浪式的流量,通过新的订阅模式,不管上游的流量如何偏移,只要不超过单个block的容量上限,消费端都能做到真正意义上的负债均衡,pop模式消费的模式已经在钉钉 m的场景磨合得非常好,在对可用性性能实验方面面要求非常高的钉钉 im 系统证明了自己可以说不断升级的 RocketMQ 是即时通信场景消息队列的不二选择。

相关文章
|
3月前
|
API 开发工具 Python
钉钉有没有获取群消息内容的接口?怎么提工单(bug反馈或技术答疑)?
钉钉有没有获取群消息内容的接口?怎么提工单(bug反馈或技术答疑)?【1月更文挑战第6天】【1月更文挑战第29篇】
114 1
|
2月前
|
传感器 监控 物联网
golang开源的可嵌入应用程序高性能的MQTT服务
golang开源的可嵌入应用程序高性能的MQTT服务
201 3
|
2月前
|
消息中间件 存储 监控
搭建消息时光机:深入探究RabbitMQ_recent_history_exchange在Spring Boot中的应用【RabbitMQ实战 二】
搭建消息时光机:深入探究RabbitMQ_recent_history_exchange在Spring Boot中的应用【RabbitMQ实战 二】
32 1
|
5月前
|
消息中间件 存储 网络协议
我们一起来学RabbitMQ 二:RabbiMQ 的 6 种模式的基本应用
我们一起来学RabbitMQ 二:RabbiMQ 的 6 种模式的基本应用
|
2月前
|
网络协议 Go 数据安全/隐私保护
golang开源的可嵌入应用程序高性能的MQTT服务
golang开源的可嵌入应用程序高性能的MQTT服务
253 2
|
9天前
|
消息中间件 存储 算法
RocketMQ学习笔记
RocketMQ学习笔记
51 0
|
22天前
|
传感器 网络协议 中间件
Mqtt学习笔记--交叉编译移植(1)
Mqtt学习笔记--交叉编译移植(1)
18 0
|
30天前
|
弹性计算 安全 前端开发
除了 Mattermost,这些开源 IM 应用也值得一试
在数字化时代,即时通讯(IM)已成为日常生活和工作的重要部分,开源IM应用因其透明度、可定制性和社区支持受到关注。
|
1月前
|
机器学习/深度学习 自然语言处理
基于深度学习的自然语言处理技术在智能客服系统中的应用
【2月更文挑战第21天】随着人工智能技术的不断发展,自然语言处理(NLP)技术在各个领域得到了广泛应用。本文主要探讨了基于深度学习的自然语言处理技术在智能客服系统中的应用。首先介绍了深度学习和自然语言处理的基本概念,然后分析了智能客服系统的工作原理和技术要求,接着详细阐述了基于深度学习的自然语言处理技术在智能客服系统中的具体应用,包括语义理解、情感分析和问答系统等。最后对基于深度学习的自然语言处理技术在智能客服系统中的优势和挑战进行了总结。
46 1
|
3月前
|
消息中间件 监控 负载均衡
Kafka高级应用:如何配置处理MQ百万级消息队列?
在大数据时代,Apache Kafka作为一款高性能的分布式消息队列系统,广泛应用于处理大规模数据流。本文将深入探讨在Kafka环境中处理百万级消息队列的高级应用技巧。
176 0