苏宁即时通信系统改造实践

一、从外采即时通信系统到自研

\n

苏宁最早出于办公的需要,考虑到外网访问权限控制及企业数据安全,没有采用QQ、微信这类公有云部署的聊天软件,而是采购了IBM的ST在公司内做私有化部署。随着日常办公中企业定制化需求的深入,业务部门对IM和OA一体化诉求的日益凸显,ST逐渐无法胜任,于是苏宁自研了一套IM系统。

\n

苏宁产品定位的发展历程,从基础通讯,到企业办公、社交一体化,再到纯对内办公用途,最终服务于内同时对外提供一体化工作平台。系统架构也随着产品定位和产品架构的改变而改变,经历了从基于XMPP开源框架搭建的1.0系统到纯自研的2.0系统,直至目前正在研发的办公一体化、多活高可用、组件化、可轻量化灵活部署的3.0系统。

\n

二、基于XMPP的1.0系统

\n

\"\"

\n

\"\"

\n

上图所示的是苏宁构建于XMPP协议系统的实现原理。在实现上每个独立的Node Server都包含完整的业务逻辑模块,服务器和服务器之间均建有长连接通道用于交换报文。通过消息的已达已读回执,来确保消息的可靠传输。

\n

上述实现方式有以下四个主要弊病:

\n

1.由于Node之间均需维持长连接,随着服务端的横向扩展,长连接数是N*(N-1),增长非常快。

\n

2.每台服务器都部署全量的服务,在部署上是种浪费,也不利于单个服务的升级和维护。

\n

3.XMPP报文按照xml格式定义,三种通讯原语message、presence和iq的无效载荷非常重,按以下所示,即使不携带任何信息,头部至少也是上百字节(1字符=2字节),如果用iq实现业务层面的心跳,那也是上百字节。

\n
\u0026lt;message  \n  to=\u0026quot;lily@jabber.org/contact\u0026quot;  \n  type=\u0026quot;chat\u0026quot; \u0026gt; \n    \u0026lt;body\u0026gt; 你好,在忙吗\u0026lt;/body\u0026gt; \n\u0026lt;/message\u0026gt; \n\n\u0026lt;presence from=\u0026quot;alice@wonderland.lit/pda\u0026quot;\u0026gt; \n  \u0026lt;show\u0026gt;xa\u0026lt;/show\u0026gt; \n  \u0026lt;status\u0026gt;down the rabbit hole!\u0026lt;/status\u0026gt; \n\u0026lt;/presence\u0026gt; \n\n\u0026lt;iq from=\u0026quot;alice@wonderland.lit/pda\u0026quot;  \n    id=\u0026quot;rr82a1z7\u0026quot; \n    to=\u0026quot;alice@wonderland.lit\u0026quot;  \n    type=\u0026quot;get\u0026quot;\u0026gt; \n  \u0026lt;query xmlns=\u0026quot;jabber:iq:roster\u0026quot;/\u0026gt; \n\u0026lt;/iq\u0026gt;\n
\n

4.XMPP框架下的标准聊天消息以id为关键字,已经在本地的消息,往往会在对服务端的历史消息请求中,再次被拉取,无法做到按需增补、查漏补缺。究其本质,是这种消息结构的设置,无法完成增量比对。

\n

采用XMPP协议也有以下三个主要优点:

\n

1.XMPP有很多开源框架支撑,Ios端有XMPPFramework,java的有smack。能快速的开发和搭建自己的系统。

\n

2.默认支持SASL和TLS的通道加密,传输更安全。

\n

3.XMPP实体的地址称为Jabber Identifier或JID,作用相当于用户id,其格式为:[node’@’]domain[’/'resource],在组网上也配有协议网关。这就支持了与其他通信系统(如AIM、ICQ、IRC、MSN Massager、RSS0.9和Yahoo Massager)的互通,也可以在架构上支持多域名的部署及互通。

\n

\"\"

\n

三、自研2.0系统

\n

\"\"

\n

\"\"

\n

为了解决1.0系统的上述问题,同时支持高可用、支持SaaS多企业,苏宁开发了自研2.0系统。

\n

在系统架构层面:

\n
  • \n
  • \n

    服务端将接入层Node Server做薄,只负责通信接入以及协议解析,使用netty作为NIO通信层框架,同时将所有业务逻辑归并到业务逻辑层Center Server,Node和Center Server都可以自由扩展, Node和Center Server建立长连接通道交换数据。

    \n\n
  • \n

    Node实现协议转换层和兼容XMPP连接方式,重构过渡期支持新老客户端互通。

    \n\n
  • \n

    提供单独的passport,支持OAuth方式与其他账号体系联合登陆。

    \n\n
\n

在业务逻辑层面:

\n
  • \n
  • \n

    支持多企业,苏宁作为一个独立的企业,企业之间互相隔离;

    \n\n
  • \n

    优化了消息归档机制;

    \n\n
  • \n

    部分数据实体增加了版本号,变更拉取更省流量;

    \n\n
  • \n

    消息按会话增加了long型序列号,离线消息由推送变成按需拉取,消息状态及已达已阅,通过消息区间来计算实现;

    \n\n
  • \n

    单点登录SOA;

    \n\n
  • \n

    增加批量接口、合并推送。

    \n\n
\n

高可用的基本要求是无单点故障,基本方法是分层 (分而治之) 与冗余 (失效转移),苏宁采取了以下措施:

\n
  • \n
  • \n

    在应用层:负载均衡,集群;

    \n\n
  • \n

    在数据层:主从复制,读写分离;

    \n\n
  • \n

    在软件质量控制上:制定代码规范标准,代码控制,自动化测试,支持灰度发布;

    \n\n
  • \n

    在日志与监控上:服务端接入调用链监控,客户端接入稳定性、性能监控。

    \n\n
\n

四、消息的多端同步、终端消息的防乱序防丢失办法

\n

2.0系统业务逻辑层面的最大变化在于对消息的处理。因为IM系统的核心问题就是要解决聊天消息的离线和在线处理,解决好这个,系统问题就等于解决了一半。

\n

我们想到的是两点:

\n

1.移除离线缓冲,变离线消息推送为上线后终端的按需拉取,确保离线消息在各个客户端上均能被同步、按需补充。

\n

2.作为配套算法,解决在线消息推送至终端时展示乱序的问题。

\n

为了做到这个我们的技术方案为:

\n

1.除消息的uuid(全局唯一标识)和ts(时间戳)以外,给消息定义long类型的seq(序列号),按会话独立编号,编号从1开始必须连续。服务端需保证任意两条同一会话内的消息,seq1 \u0026gt; seq2、ts1 \u0026gt; ts2互为充要条件;

\n

2.终端上线后,由终端主动获取最近会话列表,从而得到每个会话的最大seq。在某个会话需要展示消息时,检查该会话当前的本地消息区间,向消息服务端请求本地缺失的消息,请求以seq区间为参数发起批量请求。

\n

\"\"

\n

3.终端在收到推送消息后,如果推送消息的seq与会话的最后一条消息的seq不连续,则先把消息加入到对应的缓冲窗口,并启动定时器。在收到后续的推送消息时,先检查缓冲窗口,把连续的一批消息退出窗口并写入数据库、展示给用户。如果超过定时器的时长,消息seq还未接续,则说明消息在传输过程中发生丢失,不再等待,一次性把窗口中的消息写入数据库并展示。丢失消息的补充,则通过前述的终端主动拉取来实现。

\n

\"\"

\n

\"\"

\n

苏宁与业内典型的离线消息处理方案的差别如下图:

\n

\"\"

\n

1.移除了离线缓冲和配套数据库

\n

2.流程1改为请求最近会话的最大seq

\n

3.流程3返回最近会话的最大seq

\n

4.流程4、6改为上述技术方案图示的按需拉取

\n

五、对于高性能移动端架构的一些想法

\n

由于用户对IM系统的体验是通过终端来感知的,所谓的高性能,最终还是要靠终端的算法来完成。

\n

而具体到高性能的移动端设计这块,我觉得主要弄好以下几点:

\n

1.需要独立的组件用于支撑登陆账号和网络协议这块。

\n

\"\"

\n

2.在协议层上构建逻辑层,对于移动端的上传下载、接口调用、内部算法调用,都要有统一的线程池管理。其他服务,如断线重连、心跳服务,数据库DAO服务,缓冲服务等都在逻辑层统一封装和控制。

\n

3.服务端推送的变更,要先在数据库生效,再通知UI层生效,走消息总线通知。通知尽量细分颗粒度,变更的数据携带在通知中,避免通知接收方再去查数据库。

\n

4.如果数据库使用的是系统默认的SQLite,要避免在主线程直接进行任何数据库操作(增删改查),因为SQLite并发锁的颗粒度是文件级别的,会导致后台线程的数据库操作阻塞前台的。一方面,我们要识别和优化端上最慢的数据库操作的耗时,另一方面,全在后台操作数据库,界面就不会随机卡顿。

\n

5.在UI层还涉及到要防跳帧(用户可感知的60帧/秒–16ms/帧)。这需要持续关注和简化各个UI布局的嵌套层次,从而减少布局尺寸计算和渲染的开销。另外在android端需要特别关注内存抖动引发的跳帧:避免高频调用的方法中分配局部大对象频繁触发大GC,从而挂起主线程造成跳帧。

\n

6.没有6了,一时大脑堵塞了。

\n

六、正在研发的3.0系统

\n

移动办公已成为企业提效、降成本的有效手段之一,在企业建设移动信息化的过程中,存在以下建设痛点:

\n

\"\"

\n
  • \n
  • \n

    内部沟通渠道混乱,信息外泄风险大

    \n\n
  • \n

    移动业务繁多,使用和管理混乱

    \n\n
  • \n

    信息系统孤岛现象严重,相互隔离

    \n\n
  • \n

    缺乏通用办公应用及个性化应用开发能力

    \n\n
\n

为此苏宁正在研发办公一体化的3.0系统,具体的产品和技术架构稍后公司会通过正式渠道对外公布。

\n

七、结语

\n

个人技术面偏移动端架构,涉及服务端的实现可能阐述的不够透彻,唯希望能以有限文字多少给后来者提供些借鉴吧,谢谢。

\n
作者简介
\n

陈思佳,苏宁科技集团移动端资深架构师,主要负责苏宁移动通讯、IoT 、一体化工作平台等项目研发工作。在移动端架构方面拥有十多年的实践经验,先后就职于华为无线产品线、Motorola GSG(Global Software Group)。精通Android、iOS编程架构、开发工具,对IM协议及架构也有深厚积累。

\n

赵一唯,苏宁科技集团服务端资深架构师,主要负责易适配、邮件系统、移动办公一体化平台等项目研发工作,并为IM产品线技术第一负责人。在分布式架构方面拥有十多年的实践经验,先后就职于ZTE中兴通讯、趋势科技、IBM等公司。精通java服务端编程,对多活、高可用的解决方案有独到见解,在IM协议及架构方面也有深厚积累。

\n

更多内容,请关注前端之巅。

\n

\"\"

\n
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

flybirding10011

谢谢支持啊999

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值