IM 系统为用户与商家建立了直接沟通的渠道,帮助用户解答购买旅行产品中的问题,既匆匆成了订单交易,也帮用户打消了疑虑,匆匆成用户旅行欲望的实现。伴随着业务的快速发展,几年间,马蜂窝 IM 系统也经历了几次比较主要的架构蜕变和转型。
本文将分享马蜂窝旅游网的IM系统架构从零演进的全体过程,希望能给你的IM技能选型和方案确定带来启示。
关于马蜂窝旅游网:

马蜂窝旅游网是中国领先的自由行做事平台,由陈罡和吕刚创立于2006年,从2010年正式开始公司化运营。马蜂窝的景点、餐饮、酒店等点评信息均来自上亿用户的真实分享,每年帮助过亿的旅行者制订自由行方案。
学习互换:
- 即时通讯/推送技能开拓互换4群:101279154[推举]
- 移动端IM开拓入门文章:《新手入门一篇就够:从零开拓移动端IM》
(本文同步发布于:http://www.52im.net/thread-2675-1-1.html)
二、干系文章《一套海量在线用户的移动端IM架构设计实践分享(含详细图文)》
《一套原创分布式即时通讯(IM)系统理论架构方案》
《从零到卓越:京东客服即时通讯系统的技能架构演进进程》
《蘑菇街即时通讯/IM做事器开拓之架构选择》
《以微博类运用处景为例,总结海量社交系统的架构设计步骤》
《一套高可用、易伸缩、高并发的IM群聊、单聊架构方案设计实践》
《腾讯QQ1.4亿在线用户的技能寻衅和架构演进之路PPT》
《微信技能总监谈架构:微信之道——大道至简(演讲全文)》
《如何解读《微信技能总监谈架构:微信之道——大道至简》》
《快速裂变:见证微信强大后台架构从0到1的演进进程(一)》
三、IM 1.0:初期阶段初期为了支持业务快速上线,且当时版本流量较低,对并发哀求不高,IM 系统的技能架构紧张以大略和可用为目的,实现的功能也很根本。
IM 1.0 利用 PHP 开拓,实现了 IM 基本的用户/客服接入、收发、咨询列表管理功能。用户咨询时,会通过均匀分配的策略分配给客服,记录用户和客服的关联关系。用户/客服发送时,通过调用转发模块,将投递到对方的 Redis 壅塞行列步队里。收则通过 HTTP 长连接调用轮询模块,有时即刻返回,没有则壅塞一段韶光返回,这里壅塞的目的是降落轮询的间隔。
收发模型如下图所示:
上图模型中轮询模块的长连接要求是通过 php-fpm 挂载在壅塞行列步队上,当该要求变多时,如果不能及时开释 php-fpm 进程,会对做事器性能花费较大,负载很高。
为理解决这个问题,我们对轮询模块进行了优化,选用基于 OpenResty 框架,利用 Lua 协程的办法来优化 php-fmp 永劫光挂载的问题。Lua 协程会通过对 Nginx 转发的要求标记判断是否拦截网络要求,如果拦截,则会将壅塞操作交给 Lua 协程来处理,及时开释 php-fmp,缓解对做事器性能的花费。
优化的处理流程见下图:
四、IM 2.0:需求定制阶段伴随着业务的快速增长,IM 系统在短期内面临着大量定制需求的增加,开拓了许多新的业务模块。面对大量的用户咨询,客服的做事能力已经招架不住。
因此,IM 2.0 将重心放在提升业务功能体验上,比如:
1)在处理用户的咨询时,将从前单一的分配办法演化为采取均匀、权重、排队等多种办法;
2)为了提升客服的效率,客服的咨询回答也增加了可选配置,例如自动回答、FAQ 等。
以一个范例的用户咨询场景为例,当用户打开 App 或者网页时,会通过连接层建立长连接,之后在咨询入口发起咨询时,会携带着线索初始化链路,建立一条可复用、可检索的线;发送时,通过做事将存储到 DB 中,同时会根据线检索当前咨询是否被分配到客服,调用分配做事的目的是为当前咨询完善客服信息;末了将客服信息更新到链路关系中。
这样,一条完全的链路就建立完毕,之后用户/客服发出的通过转发做事传输给对方。
以上处理流程如下图所示:
五、IM 3.0:做事拆分阶段5.1、概述
业务量在不断积累,随着模块增加,IM 系统的代码膨胀得很快。由于代码规范没有统一、接口职责不足单一、模块间耦合较多等种缘故原由,改动一个需求很可能会影响到其它模块,使新需求的开拓和掩护本钱都很高。
为理解决这种局势,IM 系统必须要进行架构升级,紧张任务便是做事的拆分。目前,经由拆分后的 IM 系统整体分为 4 块大的做事,包括客服做事、用户做事、IM 做事、数据做事。
如下图所示:
如上图,我们来进行一下解读:
1)客服做事:环绕提升客服效率和用户体验供应多种办法,如供应群组管理、成员管理、质检做事等来提升客服团队的运营和管理水平;通过分配做事、转接手事来利用户的接待效率更灵巧高效;支持自动回答、FAQ、知识库做事等来提升客服咨询的回答效率等;
2)用户做事:剖析用户行为,为用户做兴趣推举及用户画像,以及统计用户对马蜂窝商家客服的满意度;
3)IM 做事:支持单聊和群聊模式,供应实时关照、离线推送、历史漫游、联系人、文件上传与存储、内容风控检测等;
4)数据做事:通过采集用户咨询的来源入口、是否咨询下单、是否有客服接待、用户咨询以及客服回答的韶光信息等,定义数据指标,通过数据剖析进行离线数据运算,终极对外供应数据统计信息。紧张的指标信息有 30 秒、1 分钟回答率、咨询人数、无应答次数、均匀应答韶光、咨询发卖额、咨询转化率、推举转化率、分时接待压力、值班情形、做事评分等。
5.2、用户状态流转
现有的 IM 系统 中,用户咨询时一个完全的用户状态流转如下图所示:
如上图所示:
1)用户点击咨询按钮触发事宜,此时用户状态进入初始态;
2)发送时,系统变动用户状态为待分配,通过调用分配做事分配了对应的客服后,用户状态变动为已分配、未办理;
3)当客服办理了用户或者客服回答后用户永劫光未说话,触发系统自动办理的操作,此时用户状态变动为已办理,一个咨询流程结束。
5.3、IM 做事的重构
在做事拆分的过程中,我们须要考虑特定做事的通用性、可用性和降级策略,同时须要尽可能地降落做事间的依赖,避免由于单一做事不可用导致整体做事瘫痪的风险。
在这期间,公司其它业务线对 IM 做事的利用需求也越来越多,利用频次和量级也开始加大。初期阶段的 IM 做事当连接量大时,只能通过修正代码实现水平扩容;新业务接入时,还须要在业务做事器上配置 Openresty 环境及 Lua 协程代码,业务接入非常不便,IM 做事的通用性也很差。
考虑到以上问题,我们对 IM 做事进行了全面重构,目标是将 IM 做事抽取成独立的模块,不依赖其它业务,对外供应统一的集成和调用办法。考虑到 IM 做事对并发处理高和损耗低的哀求,选择了 Go 措辞来开拓此模块。
新的 IM 做事设计如下图:
个中,比较主要的 Proxy 层和 Exchange 层供应了以下做事:
1)路由规则:例如 ip-hash、轮询、最小连接数等,通过规则将客户端散列到不同的 ChannelManager 实例上;
2)对客户端接入的管理:接入后的连接信息会同步到 DispatchTable 模块,方便 Dispatcher 进行检索;
3)ChannelManager 与客户端间的通信协议:包括客户端要求建立连接、断线重连、主动断开、心跳、关照、收发、的 QoS 等;
4)对外供应单发、群发的 REST 接口:这里须要根据场景来决定是否利用,例如用户咨询客服的场景就须要通过这个接口下发。
针对上述第“4)”点,紧张缘故原由在以下 3 点:
1)发时会有创建线、分配管家等逻辑,这些逻辑目前是 PHP 实现,IM 做事须要知道 PHP 的实行结果,一种办法是利用 Go 重新实现,其余一种办法是通过 REST 接口调用 PHP 返回,这样会带来 IM 做事和 PHP 业务过多的网络交互,影响性能;
2)转发时,ChannelManager 多个实例间须要相互通信,例如 ChannelManager1 上的用户 A 给 ChannelManager2 上的客服 B 发,如果实例间无通信机制,无法转发。当要再扩展 ChannelManager 实例时,新增实例须要和其它已存在实例分别建立通信,增加了系统扩展的繁芜度;
3)如果客户端不支持 WebSocket 协议,作为降级方案的 HTTP 长连接轮循只能用来收,发须要通过短连接来处理。其它场景不须要转发,只用来给 ChannelManager 传输的场景,可通过 WebSocket 直接发送。
5.4、改造后的 IM 做事调用流程
初始化线及分配客服过程由 PHP 业务完成。须要转发时,PHP 业务调用 Dispatcher 做事的发接口,Dispatcher 做事通过共享的 Dispatcher Table 数据,检索出吸收者所在的 ChannelManager 实例,将通过 RPC 的办法发送到实例上,ChannelManager 通过 WebSocket 将推送给客户端。
IM 做事调用流程如下图所示:
当连接数超过当前 ChannelManager 集群承载的上限时,只需扩展 ChannelManager 实例,由 ETCD 动态的关照到监听侧,从而做到平滑扩容。目前浏览器版本的 JS-SDK 已经开拓完毕,其它业务线通过接入文档,就能方便的集成 IM 做事。
在 Exchange 层的设计中,有 3 个问题须要考。
1)多端同步:
现在客户端有 PC 浏览器、Windows 客户端、H5、iOS/Android,如果一个用户登录了多端,当有过来时,须要查找出这个用户的所有连接,当用户的某个端断线后,须要定位到这一个连接。
上面提到过,连接信息都是存储在 DispatcherTable 模块中,因此 DispatcherTable 模块要能根据用户信息快速检索出连接信息。DispatcherTable 模块的设计用到了 Redis 的 Hash 存储,当客户端与 ChannelManager 建立连接后,须要同步的元数据有 uid(用户信息)、uniquefield(唯一值,一个连接对应的唯一值)、wsid(连接标示符)、clientip(客户端 ip)、serverip(做事端 ip)、channel(渠道),对应的构造大致如下:
这样通过 key(uid) 能找到一个用户多个真个连接,通过 key+field 能定位到一条连接。连接信息的默认过期韶光为 2 小时,目的是避免因客户端连接非常中断导致做事端没有捕获到,从而在 DispatcherTable 中存储了一些过期数据。
2)用户在线状态同步:
比如一个用户先后和 4 个客服咨询过,那么这个用户会涌如今 4 个客服的咨询列表里。当用户上线时,要担保 4 个客服看到用户都是在线状态。
要做到这一点有两种方案:
一种是客服通过轮询获取用户的状态,但这样当用户在线状态没有变革时,会发起很多无效的要求;
其余一种是用户上线时,给客服推送上线关照,这样会造成扩散,每一个咨询过的客服都须要扩散关照。
我们终极采纳的是第二种办法,在推送的过程中,只给在线的客服推送用户状态。
3)的不丢失,不重复:
为了避免丢失,对付采取长连接轮询办法的我们会在发起要求时,带上客户端已读的 ID,由做事端打算出差值然后返回;利用 WebSocket 办法的,做事端会在推送给客户端后,等待客户真个 ACK,如果客户端没有 ACK,做事端会考试测验多次推送。
这时就须要客户端根据 ID 做重复的处理,避免客户端可能已收到,但是由于其它缘故原由导致 ACK 确认失落败,触发重试,导致重复。
5.5、IM 做事的流
上文提到过 IM 做事须要支持多终端,同时在角色上又分为用户端和商家端,为了能让关照、在输出时根据域名、终端、角色动态输出差异化的内容,引入了 DDD (领域驱动设计)的建模方法来对进行处理。
处理过程如下图所示:
六、小结和展望伴随着马蜂窝「内容+交易」模式的不断深化,IM 系统架构也经历着蜕变和升级的不同阶段,从初期粗旷无序的模式走向统一管理,逐渐规范、形成规模。
我们取得了一些进步,当然,还有更长的路要走。未来,结合公司业务的发展脚步和团队的技能能力,我们将不断进行 IM 系统的优化。
目前我们正在操持将轮询模块中的做事端代码用 Go 更换,使其不再依赖 PHP 及 OpenResty 环境,实现更好地解耦;其余,我们将基于 TensorFlow 实现向聪慧客服的探索,通过演习数据模型、剖析数据,进一步提升人工客服的办理效率,提升用户体验,更好地为业务赋能。
附录:更多架构设计文章[1] 有关IM架构设计的文章:
《浅谈IM系统的架构设计》
《简述移动端IM开拓的那些坑:架构设计、通信协议和客户端》
《一套海量在线用户的移动端IM架构设计实践分享(含详细图文)》
《一套原创分布式即时通讯(IM)系统理论架构方案》
《从零到卓越:京东客服即时通讯系统的技能架构演进进程》
《蘑菇街即时通讯/IM做事器开拓之架构选择》
《腾讯QQ1.4亿在线用户的技能寻衅和架构演进之路PPT》
《微信后台基于韶光序的海量数据冷热分级架构设计实践》
《微信技能总监谈架构:微信之道——大道至简(演讲全文)》
《如何解读《微信技能总监谈架构:微信之道——大道至简》》
《快速裂变:见证微信强大后台架构从0到1的演进进程(一)》
《17年的实践:腾讯海量产品的技能方法论》
《移动端IM中大规模群的推送如何担保效率、实时性?》
《当代IM系统中谈天的同步和存储方案磋商》
《IM开拓根本知识补课(二):如何设计大量图片文件的做事端存储架构?》
《IM开拓根本知识补课(三):快速理解做事端数据库读写分离事理及实践建议》
《IM开拓根本知识补课(四):精确理解HTTP短连接中的Cookie、Session和Token》
《WhatsApp技能实践分享:32人工程团队创造的技能神话》
《微信朋友圈千亿访问量背后的技能寻衅和实践总结》
《王者光彩2亿用户量的背后:产品定位、技能架构、网络方案等》
《IM系统的MQ中间件选型:Kafka还是RabbitMQ?》
《腾讯资深架构师干货总结:一文读懂大型分布式系统设计的方方面面》
《以微博类运用处景为例,总结海量社交系统的架构设计步骤》
《快速理解高性能HTTP做事真个负载均衡技能事理》
《子弹短信光鲜的背后:网易云信首席架构师分享亿级IM平台的技能实践》
《知乎技能分享:从单机到2000万QPS并发的Redis高性能缓存实践之路》
《IM开拓根本知识补课(五):普通易懂,精确理解并用好MQ行列步队》
《微信技能分享:微信的海量IM谈天序列号天生实践(算法事理篇)》
《微信技能分享:微信的海量IM谈天序列号天生实践(容灾方案篇)》
《新手入门:零根本理解大型分布式架构的演进历史、技能事理、最佳实践》
《一套高可用、易伸缩、高并发的IM群聊、单聊架构方案设计实践》
《阿里技能分享:深度揭秘阿里数据库技能方案的10年变迁史》
《阿里技能分享:阿里自研金融级数据库OceanBase的艰辛发展之路》
《社交软件红包技能解密(一):全面解密QQ红包技能方案——架构、技能实现等》
《社交软件红包技能解密(二):解密微信摇一摇红包从0到1的技能演进》
《社交软件红包技能解密(三):微信摇一摇红包雨背后的技能细节》
《社交软件红包技能解密(四):微信红包系统是如何应对高并发的》
《社交软件红包技能解密(五):微信红包系统是如何实现高可用性的》
《社交软件红包技能解密(六):微信红包系统的存储层架构演进实践》
《社交软件红包技能解密(七):支付宝红包的海量高并发技能实践》
《社交软件红包技能解密(八):全面解密微博红包技能方案》
《社交软件红包技能解密(九):谈谈手Q红包的功能逻辑、容灾、运维、架构等》
《即时通讯新手入门:一文读懂什么是Nginx?它能否实现IM的负载均衡?》
《即时通讯新手入门:快速理解RPC技能——基本观点、事理和用场》
《多维度比拟5款主飘泊布式MQ行列步队,妈妈再也不担心我的技能选型了》
《从游击队到正规军:马蜂窝旅游网的IM系统架构演进之路》
>> 更多同类文章 ……
[2] 更多其它架构设计干系文章:
《腾讯资深架构师干货总结:一文读懂大型分布式系统设计的方方面面》
《快速理解高性能HTTP做事真个负载均衡技能事理》
《子弹短信光鲜的背后:网易云信首席架构师分享亿级IM平台的技能实践》
《知乎技能分享:从单机到2000万QPS并发的Redis高性能缓存实践之路》
《新手入门:零根本理解大型分布式架构的演进历史、技能事理、最佳实践》
《阿里技能分享:深度揭秘阿里数据库技能方案的10年变迁史》
《阿里技能分享:阿里自研金融级数据库OceanBase的艰辛发展之路》
《达达O2O后台架构演进实践:从0到4000高并发要求背后的努力》
《精良后端架构师必会知识:史上最全MySQL大表优化方案总结》
《小米技能分享:解密小米抢购系统千万高并发架构的演进和实践》
《一篇读懂分布式架构下的负载均衡技能:分类、事理、算法、常见方案等》
《普通易懂:如何设计能支撑百万并发的数据库架构?》
《多维度比拟5款主飘泊布式MQ行列步队,妈妈再也不担心我的技能选型了》
《重新手到架构师,一篇就够:从100到1000万高并发的架构演进之路》
>> 更多同类文章 ……
(本文同步发布于:http://www.52im.net/thread-2675-1-1.html)