基于Go的马蜂窝旅游网分布式IM系统技术实践
一、引言
即时通讯(IM)功能对于电商平台来说非常重要,特别是旅游电商。
从商品复杂性来看,一个旅游商品可能会包括用户在未来一段时间的衣、食、住、行等方方面面。从消费金额来看,往往单次消费额度较大。对目的地的陌生、在行程中可能的问题,这些因素使用户在购买前、中、后都存在和商家沟通的强烈需求。可以说,一个好用的 IM 可以在一定程度上对企业电商业务的 GMV 起到促进作用。
本文我们将结合马蜂窝旅游电商IM系统的发展历程,单独介绍基于Go重构分布式IM系统过程中的实践和总结(本文相当于《从游击队到正规军(一):马蜂窝旅游网的IM系统架构演进之路》一文的进阶篇),希望可以给有相似问题的朋友一些借鉴。
另外:如果你对Go在高并发系统中的应用感兴趣,即时通讯网的以下两篇也值得一读:
《Go语言构建千万级在线的高并发消息推送系统实践(来自360公司)》《12306抢票带来的启示:看我如何用Go实现百万QPS的秒杀系统(含源码)》
系列文章:
《从游击队到正规军(一):马蜂窝旅游网的IM系统架构演进之路》《从游击队到正规军(二):马蜂窝旅游网的IM客户端架构演进和实践总结》《从游击队到正规军(三):基于Go的马蜂窝旅游网分布式IM系统技术实践》(* 本文)
关于马蜂窝旅游网:
马蜂窝旅游网是中国领先的自由行服务平台,由陈罡和吕刚创立于2006年,从2010年正式开始公司化运营。马蜂窝的景点、餐饮、酒店等点评信息均来自上亿用户的真实分享,每年帮助过亿的旅行者制定自由行方案。
学习交流:
- 即时通讯/推送技术开发交流5群:215477170 [推荐]- 移动端IM开发入门文章:《新手入门一篇就够:从零开发移动端IM》
(本文同步发布于:http://www.52im.net/thread-2909-1-1.html)
二、相关文章
《一套海量在线用户的移动端IM架构设计实践分享(含详细图文)》《一套原创分布式即时通讯(IM)系统理论架构方案》《从零到卓越:京东客服即时通讯系统的技术架构演进历程》《蘑菇街即时通讯/IM服务器开发之架构选择》《以微博类应用场景为例,总结海量社交系统的架构设计步骤》《一套高可用、易伸缩、高并发的IM群聊、单聊架构方案设计实践》《腾讯QQ1.4亿在线用户的技术挑战和架构演进之路PPT》《微信技术总监谈架构:微信之道——大道至简(演讲全文)》《如何解读《微信技术总监谈架构:微信之道——大道至简》》《快速裂变:见证微信强大后台架构从0到1的演进历程(一)》《瓜子IM智能客服系统的数据架构设计(整理自现场演讲,有配套PPT)》《阿里钉钉技术分享:企业级IM王者——钉钉在后端架构上的过人之处》
三、技术背景和问题
与广义上的即时通讯不同,电商各业务线有其特有业务逻辑,如客服聊天系统的客人分配逻辑、敏感词检测逻辑等,这些往往要耦合进通信流程中。随着接入业务线越来越多,即时通讯服务冗余度会越来越高。同时整个消息链路追溯复杂,服务稳定性很受业务逻辑的影响。
之前我们 IM 应用中的消息推送主要基于轮询技术,消息轮询模块的长连接请求是通过 php-fpm 挂载在阻塞队列上实现。当请求量较大时,如果不能及时释放 php-fpm 进程,对服务器的性能消耗很大。
为了解决这个问题,我们曾用 OpenResty+Lua 的方式进行改造,利用 Lua 协程的方式将整体的 polling 的能力从 PHP 转交到 Lua 处理,释放一部 PHP 的压力。这种方式虽然能提升一部分性能,但 PHP-Lua 的混合异构模式,使系统在使用、升级、调试和维护上都很麻烦,通用性也较差,很多业务场景下还是要依赖 PHP 接口,优化效果并不明显。
为了解决以上问题,我们决定结合电商 IM 的特定背景对 IM 服务进行重构,核心是实现业务逻辑和即时通讯服务的分离。
更多有关马蜂窝旅游网的IM系统架构的演进过程,请详读:《从游击队到正规军(一):马蜂窝旅游网的IM系统架构演进之路》一文,在此不再赘述。
四、基于Go的双层分布式IM架构
4.1、实现目标
1)业务解耦:
将业务逻辑与通信流程剥离,使 IM 服务架构更加清晰,实现与电商 IM 业务逻辑的完全分离,保证服务稳定性。
2)接入方式灵活:
之前新业务接入时,需要在业务服务器上配置 OpenResty 环境及 Lua 协程代码,非常不便,IM 服务的通用性也很差。考虑到现有业务的实际情况,我们希望 IM 系统可以提供 HTTP 和 WebSocket 两种接入方式,供业务方根据不同的场景来灵活使用。
比如已经接入且运行良好的电商定制化团队的待办系统、定制游抢单系统、投诉系统等下行相关的系统等,这些业务没有明显的高并发需求,可以通过 HTTP 方式迅速接入,不需要熟悉稍显复杂的 WebSocket 协议,进而降低不必要的研发成本。
3)架构可扩展:
为了应对业务的持续增长给系统性能带来的挑战,我们考虑用分布式架构来设计即时通讯服务,使系统具有持续扩展及提升的能力。
4.2、语言选择
目前,马蜂窝技术体系主要包括 PHP,Java,Golang,技术栈比较丰富,使业务做选型时可以根据问题场景选择更合适的工具和语言。
结合 IM 具体应用场景,我们选择 Go 的原因包括:
1)运行性能:在性能上,尤其是针对网络通信等 IO 密集型应用场景。Go 系统的性能更接近 C/C++;2)开发效率:Go 使用起来简单,代码编写效率高,上手也很快,尤其是对于有一定 C++ 基础的开发者,一周就能上手写代码了。4.3、架构设计
整体架构图如下:
名词解释:
1)客户:一般指购买商品的用户;2)商家:提供服务的供应商,商家会有客服人员,提供给客户一个在线咨询的作用;3)分发模块:即 Dispatcher,提供消息分发的给指定的工作模块的桥接作用;4)工作模块:即 Worker 服务器,用来提供 WebSocket 服务,是真正工作的一个模块。架构分层:
1)展示层:提供 HTTP 和 WebSocket 两种接入方式;2)业务层:负责初始化消息线和业务逻辑处理。如果客户端以 HTTP 方式接入,会以 JSON 格式把消息发送给业务服务器进行消息解码、客服分配、敏感词过滤,然后下发到消息分发模块准备下一步的转换;通过 WebSocket 接入的业务则不需要消息分发,直接以 WebSocket 方式发送至消息处理模块中;3)服务层:由消息分发和消息处理这两层组成,分别以分布式的方式部署多个 Dispatcher 和 Worker 节点。Dispatcher 负责检索出接收者所在的服务器位置,将消息以 RPC 的方式发送到合适的 Worker 上,再由消息处理模块通过 WebSocket 把消息推送给客户端;4)数据层:Redis 集群,记录用户身份、连接信息、客户端平台(移动端、网页端、桌面端)等组成的唯一 Key。(本文同步发布于:http://www.52im.net/thread-2909-1-1.html
举报/反馈