转:融云的实践经验
http://toutiao.com/a6278194319489892609/?tt_from=weixin&utm_campaign=client_share&app=news_article&utm_source=weixin&iid=4155521039&utm_medium=toutiao_android&wxshare_count=1
QCon 北京2016全球软件开发大会已于4月23日在北京国际会议中心顺利闭幕。在23日进行的“移动开发与即时通讯”专场活动中,来自融云的技术副总裁杨威,分享了他多年工作当中所获得的心得与经验。
融云作为全球最大的即时通讯云服务商,截至2月份,已经累计服务包括土豆、秒拍、百姓网、优信二手车、驾考宝典、大智慧、战旗 TV等在内的 App 逾8万款,日活跃用户量超过2000万,日消息量超过12亿条。在艾瑞咨询最新发布的《2016年中国 IM 云服务行业白皮书》中,融云即时通讯云稳居市场第一。
当前,移动开发者无论是构建用户生态,还是丰富业务场景,亦或是打造移动办公,所以如何使用即时通讯云,也成为了企业或者开发者必须关注的议题,此次分享,融云杨威的演讲内容涉及融云 IM SDK 架构、IM SDK 实现过程中的经验等,为正在移动端开发的技术人员提供了大量的技术参考与实践经验。
以下是演讲精彩内容:
大家好,首先介绍一下我自己,我是北京邮电大学通信工程本科硕士毕业,前通信圈人士,曾从事11年手机研发,现在融云担任技术管理工作,主要负责 Android,iOS,Web 端的即时通信 SDK。融云是一家提供即时通信(IM)云服务能力的厂商。我们的核心技术团队主要来自于前飞信的后端团队,和来自三星的移动端团队。我们的前端团队以前主要负责多媒体技术和通信RCS技术,RCS 是一种电信级领域的即时通信 IM 技术。所以也都是这个领域内的资深从业人士。
从电信领域转到互联网领域做社交 IM,我们发现互联网行业的特点是快,开发快上线快。对即时通信的需求很大。互联网圈的朋友们,开发者,架构师,对即时通信技术一般都兴趣很高。今天的主题,背后有一个核心思想,就是关于技术选择”。对于我们每一位研发工程师,架构师,技术管理者,你的每一次技术选择,对自己,对公司,都是价值千金,每一次选择都影响着很多资源的投入。做出正确的选择需要信心,需要成功的经验用来参考。今天我分享的是基于我们众多工程师十几年研发经验,几万开发者得来的宝贵经验,我们愿意分享给大家,让大家在 IM 技术研发上做出最好的选择。最近几天我也参与了大会的其他一些分享,其中也涉及即时通信消息,看了之后我更加确信我们融云在这件事上真的是很专业,有很多值得分享给大家的经验,但时间有限,所以我简单的介绍。
我们这次要分享的内容是,首先介绍一下融云,然后介绍一下融云 IM SDK 架构,第三部分是分享一下 IM SDK 实现过程中那些价值千金的经验,最后分享通过 IM 社交如何实现 SaaS 级的服务。
首先,融云提供了一个 IM 的云服务平台,这是一个公有云平台。其次,融云提供了一个前端 SDK。这两部分是这个图里面绿色的部分。通过我们的云平台和 SDK,App 之间可以通过收发消息进行互动。最后,我们基于这个平台,提供了一些 SaaS 级的软件服务。对于即时通信平台,我们很多研发人员都是很有情怀的,都像自己做一次 IM,同时有微信这种巨头的存在,很多 App也都有梦想去做一个微信。但总的来说,消息要做到高并发,不丢消息,实时性是非常难的。有些业务,你通过延迟来解决并发问题,或者通过丢包来解决,但对于消息,是一条也不能丢不能延迟的。
今天的分享我们主要是移动前端。SDK 前端架构是三个部分,协议栈,IMLib,IMKit。我们选用了 native 语言,即 C++ 来实现协议栈部分,并封装了两个 SDK,一个通信能力 SDK,一个界面组建 SDK,通过通信能力 SDK,你可以简单的收发消息,通过界面组件 SDK,你可以在短时间内迅速的搭建一个整套 IM 社交软件。这三部分的划分应该说是比较经典的,曾被很多业内伙伴的所借鉴。
这里额外聊一下我们对 SDK 在移动端开发的趋势。第一,云服务+SDK 的模式在移动互联网领域,经过一段时间的发展,已经趋于非常成熟了。App 通过嵌入 SDK,实现云服务能力,可以实现快速上线,节省大量的研发运维费用,同时云服务企业自己发展在技术和资金上也越来越强大,大家可以放心选用。第二,核心功能组件通过 SDK 进行封装,是一种基本的技术实践能力。各个公司也都是这么实践的,封装 SDK 的过程本身就是解耦合的过程,资深工程师都知道解耦合是提高软件性能的一个必要过程。其次,封装 SDK 可以提高项目源代码管理的编译消息。最后,可以提高跨部门研发的沟通消息,大家知道程序员最高效的沟通效率是什么吗,就是不沟通。不要说话,不要解释,不要互相说服,你写的 API 我能看懂然后我去调用就可以了。当然这是个笑话,当然是越多沟通越好,比如来参加 QCon 大会听听大家的分享。
接下来分享我们第一个有价值的经验,IM 协议的选择。
我参与过一些活动和社群里,我们发现大家都对如果实现一个 IM 有很高的兴趣。第一个面对的选择就是如何去选择和实现 IM 协议,有了协议才有后面的一切。很多人都在关心,我该选择 XMPP 还是私有协议呢。我个人的看法是,移动互联网和计算机技术发展到今天,已经可以替 XMPP 宣告死刑了,到目前为止所有的大型商业机构采用 XMPP 搭建的通信网络要么替换了要么关闭了,运行中的也有一些不多。所以,大家不要去选择 XMPP 构建自己的商业 App IM 功能,当做自学还是很不错的,毕竟服务端都是开源的。XMPP 的两个主要问题是,第一基于 XML 的协议体比较重,对其压缩和解析又耗费内存,第二是其后端设计和开源架构有一些问题,当你的用户体量大了之后非常耗费服务器资源,而且常见在十万用户数量级上频繁的重连和丢消息。这个数据主要来自于一些我们客户的经验,并不是绝对准确。那么我们选择什么呢,我们推荐使用 MQTT,或者参考其思路去设计自己的私有协议。序列化我们推荐 ProtoBuf,这也是 Google 推荐的。选择私有化协议的优点是轻量,轻量处理起来就快,节省前后端资源,省电,这都是移动互联网 App 和核心需求。此外私有协议也会相对更加安全。
商业 IM 软件还要考虑跨平台。要支持 Android,iOS,WP,PC,Web 端,甚至 Linux 设备。因此在设计和选择之初就要考虑到,否则未来每一个平台和语言都要重新开发一次。我们的协议栈使用 C++开发,基于 Linux,因此可以无缝的兼容几乎所有平台。注意这个图里我们把业务和数据库放到了 native 协议栈部分,这个核心优点是跨平台统一,可以保证每一个细节甚至是响应时间,都可以在多平台一致。业务和数据是否放在 native 对于架构师是比较重要的一个选择。数据库和业务层跟 natvie 协议栈在一起还有一个重要的原因,就是更快的响应和处理消息,当接收到消息的时候,我们会首先给服务端发响应包,这样服务器更快的释放资源。然后移动端在继续进行后续的处理。业务数据和协议都通过 native 实现,可以更好的处理这部分逻辑。凡事有利就有弊,这个缺点也是有的,在 Android 上由于 NDK 编译会导致库文件比较大,而国内 Android App 一般对体积要求比加大。解决办法是不断的优化更新减少尺寸。这部分稍后还会介绍。
第二个有价值的经验是 SDK 的实现。我们封装了两个 SDK。IMLib 和 IMKit,其中 IMLib 主要负责能力,建立连接和发送消息等功能。IMLib 实现的是一个跟微信风格类似的界面。相比之下很多产品一般只会选择一个类似 IMLib 这样的能力 SDK。做出这个选择的根源是我们希望节省开发者的时间,共同的部门实现一次就可以了,不需要第二次第三次反复开发,既然80%的 IM 社交界面都是类似的,那么融云实现了提供一个标准的模式就可以了。开发者的创意是无限的,还有20%的需求我们满足不了,那么使用我们的通信组件 IMLib 就可以了。我们做这个界面 SDK 基于一个价值观:所见即所得。客户看到我们宣传的界面是这样的,集成了 SDK 之后得到的也是这样的。不会像有的产品宣传的无所不能,其实只是方便面包装上的效果图,都要等着客户自己去实现。
介绍一下IMkit组件的架构,大家看图即可。主要是封装了两个界面:会话列表和会话。Android 和 iOS上设计架构略有区别。有很多工程师也纠结这个问题,是否应该让 Android 工程师和 iOS 工程师使用同样的设计模式,我们的经验是让各种的工程师使用各自的架构,在业务上划分好就可以了。MVC,MVVM,MVP,本质上就是显示层、控制层和数据层的划分。重要的是划分好层次即可。让一类工程师去学习另外一类工程师的开发习惯效果不好。这个经验来自我们融云几万开发者。第二条经验是融云自己内部的经验,我们不适用第三方组件,比如说HTTP 和数据库的第三方组件。第三条是持续的优化结耦,这也跟今天所有类似经验一样,选择之后一定是有利有弊,针对弊端,要不断的去优化。
我们为什么选择做一个界面SDK 呢,因为实际上在移动端,UI 的开发量是极大的,一般占 80%以上。输入区,表情,图片选择器,会话界面,消息展现等等,一般需要一个工程师1个月的时间开发,1个月的时间调试。两个端就是4~6个月。而且老板和产品经理还觉得很容易,虽然确实是不难,但是其实细节上做出来性能效果差别都很大的。我们的一个价值观就是:我们每多做一些,开发者就少做一些,所以我们选择把界面封装起来替客户做完。当然也有缺点,IMKit 是一个非常重的封装模式,接口很多,使用方式复杂,我们选择不断的去优化,未来我们会进一步解耦合把核心的部分再次封装。另外我们融云的客户支持服务工作做的很好,可以提工单像我们咨询。我们每天有很多研发工程师回复200个左右的客户工单问题,在此也感谢我们融云这些工程师。
再介绍一下IMLib的架构,同样大家看图理解吧。我们封装了两个核心象,Conversation,Message,这个对象是跨平台一致的。lib提供了像 connect、sendMesage这样的接口,同时我们做了很多工作,让网络连接更加稳定性。不需要客户去做重连。很多朋友关心长连接和稳定和优化,其实长连接就是通过发送心跳包维持,并没有什么秘密。最差的结果就是多重试几次,但我们不能这样,我们必须确保客户得到的版本性能是最优的,所以关键是持之以恒的优化,发现问题并解决问题。我们每个版本都监控电量、流量、内存。确保性能最优。
第三个有价值的经验是正确的版本迭代姿势。也是今天的点睛之笔。前面介绍的技术选择,不能说绝对正确,但也都是基于我们融云资深团队这么多年的经验,几万开发者的集成经验。有优点也有缺点,那么通过什么方式弥补优点就很重要。比如使用 native 语言实现协议栈,优点很多,但缺点是 Android 上的包比较大。那么解决的办法就是不断优化每一行代码去优化包的大小。提供 IMKit 的优点是节省了用户的时间,但是缺点就是支持使用复杂,那么我们就进一步去拆解和封装。技术选择只是第一步,之后的不断持续优化才是一切。
这张图是融云至今为止发布的 220 多个版本道路中的一部分,横轴是从2015年1月到2016年4月也就是现在,纵轴是我们衡量的一个性能参数,基于尺寸,电量,性能综合评价。在这里我们分享一下我们成功经验,也分享一下不那么成功的经验,融云于创业之初发布了1.0版本,最初版本的要求一定是快速上线,快速支持客户。但是在业务量体量到一定规模的时候,你的架构可能是支撑不住的,所以一定要做一次架构的重构,这个情况在很多人身上都出现过。当时我们采用了一次大的架构更新。导致了 1.0 和 2.0 两个版本在几个月内并行,架构升级一定是性能的提高功能的增加。但这次升级并不能成为成功,因为长时间版本并行,给客户带来了一定的烦恼。这个现象融云遇到了,很多人也遇到了,即使现在我们的圈内伙伴内还在进行类似的升级。那么正确的姿势是什么呢,我们可以看到从2015年8月开始到现在,我们的整体功能增加了 32%,协议栈包降低了 75.7%,Android/iOS 源代码量减少了 36.8,电量优化了 36% ~ 77% 不等。而用户完全无感知。我们的版本号没有变化,但其实代码已经大变样。我认为身为一个架构师,不应该让用户通过版本号增加去感知你架构的改变。这是我们很骄傲的一件事,我们在一年的时间内通过不断迭代、追求卓越的的互联网精神,持续的提高着软件质量,给客户带来更好的性能,更小的尺寸,更加省电。这才是我们正确的开发者服务精神。
所以结合起来说就是,做出正确的选择,通过不断的迭代努力去优化自己的产品,永不停止。
第三部分,我们讲一些融云如何实现 SaaS 级的体验和服务。SaaS = Software as a Service,软件即服务,在互联网时代,SaaS 的核心是“一经要求,即可使用”,最佳实践是通过浏览器,打开一个网页就可以使用。在移动互联网时代,实现 SaaS 服务的难度相对大了一些。我认为移动互联网时代的 App 就是互联网时代的浏览器,同样是入口,区别是移动互联网上的入口多了一些。用户进入一个 App,进行他的核心体验的同时,也会发消息,也会打电话,购物,发红包,这些体验可以在 App 内闭环完成。这对 App 厂家们来说是一种核心需求,对用户来说也是一种最佳体验。要实现这些功能和能力,仅靠 App 厂家自己是不行的,这意味要重复建设很大的研发团队。因此需要集成第三方服务,需要集成 SDK 发布版本,这一步是无法跳过的,但在集成之后,服务是可以反复体验的。所以我们融云的目标是提供一种 SaaS 级的体验,一经集成,即可使用。
融云在这方面有比较好的实践经验,融云提供的是即时通信 IM,是一种通信能力,我们并不做具体的 SaaS 业务,比如客服。但我们的很多客户都需要客服,需要一个完整功能强大的客服工作台,于是我们选择了跟市面上最优秀的一些厂商合作,通过融云 SDK,让客户可以在移动端使用 IM,在 PC 端使用客服工作台。这个技术方案大概如图,首先要在客户端实现功能抽象化,把标准的客服功能抽象化为具体的消息,然后通过在服务端实现一个消息转 API 的适配层,直接访问客服合作伙伴的服务器。这个实践模式看起来简单,其实这并不是唯一选择,但他是最优的,效率高性能好,合作伙伴不需要改变自己的设计架构。我们可以同时支持多家客服后台,而移动端抽象化之后,对后台使用的是谁完全无感知,只是基于标准的信令去做处理。而对客户来说,服务端可以动态的控制和调整使用哪个后台,增加了更多的选择。
客服是我们的第一类实践,我们的第二类实践是对音视频产品能力的整合,对于有些客户需要的视频电话,视频直播聊天室等能力,融云也选择了市场上最好的产品,替客户封装好。区别于客服的实践场景,移动端必须使用两个 SDK,在移动端增加适配层。这类产品融云现在支持比较好的直播聊天室,因为融云的 IM 聊天室能力非常强大,今年视频直播业务火爆之后,非常多的客户找融云提供可以支持超大量并发的聊天室,因此我们把聊天室跟视频直播进行了一个比较好的封装和整合,方便客户更加容易的使用。介绍这两种优秀的实践模式,除了适合企业开发领域,其实更加适合各个 App 厂商去根据自己的需求集成第三方服务,可以更加灵活的把第三方 SDK 和云服务集成到自己的 App 里。
最后谢谢主办方,谢谢大家。