IM推送保障及网络优化详解(二):如何做长连接加推送组合方案
对于移动APP来说,IM功能正变得越来越重要,它能够创建起人与人之间的连接。社交类产品中,用户与用户之间的沟通可以产生出更好的用户粘性。
在复杂的 Android 生态环境下,多种因素都会造成消息推送不能及时达到客户端。另外,不稳定的移动网络也给数据传输的速率和可靠性增加了障碍。
本文详解了网易云信IM SDK在应对弱网环境、移动端硬件限制以及Android复杂的生态现状时的探索与心得.如何实现不影响用户体验的后台保活,改善的长连接加推送组合方案,以及在弱网环境大数据传输的优化实践。
相关阅读推荐:
网易云信即时通讯推送保障及网络优化详解(一)如何做长连接加推送组合方案
网易云信即时通讯推送保障及网络优化详解(三)如何在弱网环境下优化大数据传输
如何做长连接
对于IM来说,及时的消息推送和较低的电量消耗也并非不可兼得。在传统上,每个IM客户端都会各自维护一条与服务器的长连接,自己的消息和信令都在这条长连接上传递,每个APP也独自去心跳,断线重连等事情。
这种模式比较简单,不同的APP也是完全隔离的,不会互相影响。但他的缺点也非常明显,首先是做了很多重复的事情,造成了流量和电量的无谓消耗;第二是要保证所有的进程都能在后台运行很难。优化的方向也就非常明显了,那就是共享连接,现在绝大部分推送SDK也是这么做的。从这些APP里面选出一个当前正在运行的,或者是被杀概率最低的APP作为总代理,只由这个代理和服务器建立连接,一个手机上的所有其他APP都通过这个代理中转与服务器通信。但是,IM有一个很基本的要求在这种模式下无法得到满足:安全。所有APP的消息都经过代理中转,代理到服务器的连接是加密的,安全的,但到了代理这里,消息都被解开了,因此代理理论上可以看到其他所有APP的来往消息。因此,这种共享长连接的方式并不适用于IM。
虽然共享长连接方式不合适,但仍然提供了一个优化的思路。在此基础上,有另一个可以脱敏共享连接的方式:安全长连接加推送连接模式。
每个APP在使用和真正传递数据时,仍然独立使用自己的安全长连接。而当APP退到后台一段时间之后,则断开长连接,然后每个APP开启一个推送代理,并选择其中一个和网易云信的推送服务器建立连接,之后当APP有新消息时,就通过这个推送连接传递。APP可以自己控制发出的推送消息的安全级别,可以是包含说话人和消息内容,可以只包含说话人,或者只是一条简单的有新消息到达的提醒文案。推送到达后,如果是代理APP自己的消息,直接传递给代理APP即可。如果是其他APP消息,前面说到过,直接唤醒可能会失败,而且会导致无谓的电量消耗,所以这里并不直接将提醒传递给目标APP,而是由带来发出一条通知栏提醒。等用户去点击通知栏提醒后,才会把目标APP唤醒。
现在国内的ROM中,华为和小米的系统本来是带有推送系统,且开放给了第三方APP的。在这两个系统上,使用系统的推送通道明显会更加稳定,也更加节省资源。因此在MIUI上,从长连接到推送通道的切换流程仍然和前面的一样,只是不再使用自己的推送连接,而是将消息转发到MIUI的推送服务器,然后转给MIUI系统的推送代理,然后传递给网易云信的APP。华为的推送系统流程也是一样。不过现在华为和MIUI在推送实现上有一些区别,例如MIUI的通知栏提醒是在自己的推送代理里完成的,而华为却是将提醒通知交给APP自己去完成的,另外,他们的通知栏提醒的管理接口也有很多区别。在APP没有被禁用的情况下,两者都可以收到推送,而如果APP已经被禁用了,MIUI的通知栏提醒方式还可以将推送送达,而其他的推送方式则不能送达了。
以上就是在保障消息推送方面所能够做的所有事情了。如果以后有更多的系统开放自己的推送系统也可以选择逐步接入,以提高推送到达即时性,减少资源消耗。不过相应的,也要承受不断加入各种系统的推送SDK,增大发布包体积的缺点。
移动通信网络的三个特点
第一个是慢,尤其是2G,3G网络,慢的令人发指。
第二个是断,手机跟着人不停的移动,网络也不停的在切换,从wifi到移动网络,从一个基站到另一个基站,从有信号到没信号,都可能导致网络中断。有些制式的网络,接打电话也会导致数据网络断开。另外,移动基站还有NAT超时,到一个连接上长时间空闲后,基站就会默默的将连接断开,没有任何通知。
第三个是贵,这个就不用多说。
三种长连接类型
在网易云信整个通信系统中有3种类型的连接:TCP,UDP,HTTP。虽说这三个并不是同一层的协议,不过毕竟都在应用的更下层,因此这么划分也无妨。3种类型的协议对应了不同的业务应用。TCP主要是用户长连接,也就是普通IM消息和信令的传输,UDP用于传输实时音视频数据流,而HTTP则主要用在音频,图片等文件的上传下载上。对于不同的业务,SDK优化的关注点会有一些不相同。

IM长连接优化怎么做?
第一个是协议的选择。前面说,长连接的使用量是最大,选择一个合适的协议至关重要。如果是刚开始接触IM开发,一般会选择一些开源的协议,比如XMPP,SIP等。这是XMPP协议的一个请求样例,可以看到是一段XML格式的文本数据。

这是基于SIP的SIMPLE协议的一个请求样例,可以看到是一段类似HTTP协议的文本数据。这些协议的优势在于开源,有成熟的解决方案可以使用,扩展性好,甚至还可以和其他系统互联互通,协议的可读性也非常好。但是在普遍比较臃肿,冗余字段很多,在昂贵的移动网络里面用起来会比较浪费。网易云信采用的是私有的二进制协议,这是一个请求的数据样例,这里是把二进制数据转为了16进制显示出来,每个字节这里显示为两个字符。可以看到二进制协议的特点在于完全失去了可读性,但是,却带来极高的表达效率,相对于文本协议,可以节省非常多的数据流量。
另一个例子是登录的优化。由于移动网络经常断开,所以登录常常是心跳之外交互最多的协议了。使用量越大,优化就越有意义。一般而言,登录会经过这么几步。

第一步是LBS。这里的LBS不是经常说的基于地址位置的服务,在不同的厂商可能也有不同的叫法,反正作用都是获取服务器的IP地址。像云信这种需要提供全球服务的系统,在世界各地都要部署服务器,用户登录时,肯定要选择一台最优的服务器接入服务。通过lbs,客户端可以获取离自己最近,连通性最好的服务器连接机IP地址,服务器也可以据此做负载均衡。
拿到服务器连接机IP后,客户端就去连接该服务器。
连接成功,需要有一次握手。这个握手不是TCP的三次握手,而是为了建立安全连接,同服务器协商加密算法和加密密钥。
然后就发送登录请求,这里会带上用户认证信息,本机设备信息等数据。
登录成功之后,就是同步数据,包括离线消息,用户信息,群组信息等。一般而言,这里不会去做全量同步,而是采用基于时间戳的增量同步。
在移动网络上,每一次交互都需要比较长的时间,同时,每一次网络请求电量消耗也是很大的。所以,优化的方向就是尽量减少交互次数,而方法则是合并请求,并行操作以及省略请求。
LBS和连接这两个步骤是可以并行完成的。如果前面已经获取过LBS,这里可以有之前的缓存地址,如果没有,可以先连一个默认地址。
其次是握手和登录也可以并行操作。在握手包中,就可以把加密后的登录包直接带上去了。如果是断线重连,网易还可以简化登录,直接带上上一次登录的会话ID,一来减少服务器鉴权压力,二则可以直接带回在断线期间是否有未读消息等数据,如果没有,则能直接将同步这一步省略掉。如果有,同步也可以只做部分同步,只去拉去离线消息即可。等到APP切换到前台,才去同步其他的信息。
通过这些优化,登录时间可以降为原来的1/2到1/3,登录的流量消耗也可以节省30%左右。
IM推送保障及网络优化详解(二):如何做长连接加推送组合方案的更多相关文章
- IM推送保障及网络优化详解(一):如何实现不影响用户体验的后台保活
对于移动APP来说,IM功能正变得越来越重要,它能够创建起人与人之间的连接.社交类产品中,用户与用户之间的沟通可以产生出更好的用户粘性. 在复杂的 Android 生态环境下,多种因素都会造成消息推送 ...
- Comet技术详解:基于HTTP长连接的Web端实时通信技术
前言 一般来说,Web端即时通讯技术因受限于浏览器的设计限制,一直以来实现起来并不容易,主流的Web端即时通讯方案大致有4种:传统Ajax短轮询.Comet技术.WebSocket技术.SSE(Ser ...
- P2P技术详解(二):P2P中的NAT穿越(打洞)方案详解
1.内容概述 P2P即点对点通信,或称为对等联网,与传统的服务器客户端模式(如下图"P2P结构模型"所示)有着明显的区别,在即时通讯方案中应用广泛(比如IM应用中的实时音视频通信. ...
- .NET DLL 保护措施详解(二)关于性能的测试
先说结果: 加了缓存的结果与C#原生代码差异不大了 我对三种方式进行了测试: 第一种,每次调用均动态编译 第二种,缓存编译好的对象 第三种,直接调用原生C#代码 .net dll保护系列 ------ ...
- PopUpWindow使用详解(二)——进阶及答疑
相关文章:1.<PopUpWindow使用详解(一)——基本使用>2.<PopUpWindow使用详解(二)——进阶及答疑> 上篇为大家基本讲述了有关PopupWindow ...
- Android 布局学习之——Layout(布局)详解二(常见布局和布局参数)
[Android布局学习系列] 1.Android 布局学习之——Layout(布局)详解一 2.Android 布局学习之——Layout(布局)详解二(常见布局和布局参数) 3.And ...
- logback -- 配置详解 -- 二 -- <appender>
附: logback.xml实例 logback -- 配置详解 -- 一 -- <configuration>及子节点 logback -- 配置详解 -- 二 -- <appen ...
- 爬虫入门之urllib库详解(二)
爬虫入门之urllib库详解(二) 1 urllib模块 urllib模块是一个运用于URL的包 urllib.request用于访问和读取URLS urllib.error包括了所有urllib.r ...
- phpExcel常用方法详解【附有php导出excel加超级链接】
phpExcel常用方法详解[附有php导出excel加超级链接] 发表于4年前(-- :) 阅读() | 评论() 0人收藏此文章, 我要收藏 赞0 http://www.codeplex.com/ ...
随机推荐
- TBB、OpenCV混合编程
TBB提供了Parallel_for.Parallel_do.Parallel_reduce等通用并行算法,可以应用在不同的并行算法场合,Parallel_for适合用在多个数据或请求之间彼此没有依赖 ...
- Xcode 4.5( iOS6 SDK)、旧版本号cocos2d,支持iPhone5解析度
支持iPhone5全屏 1假设没有支持iPhone5是否.直接运行程序可以准备提交.开放iPhone5模拟器,你会发现上面有黑色的程序.没有矩形. 2真正运行该程序时,.你会发现程序回程屏幕高度.它是 ...
- Qt程序调试之Q_ASSERT断言(条件为真则跳过,否则直接异常+崩溃)
在使用Qt开发大型软件时,难免要调试程序,以确保程序内的运算结果符合我们的预期.在不符合预期结果时,就直接将程序断下,以便我们修改. 这就用到了Qt中的调试断言 - Q_ASSERT. 用一个小例子来 ...
- matlab 微积分
符号变量,symbolic variable 1. 高阶导数 高阶导数的计算,当然可以用手工的方式,但显然这种机械重复的推导,更适用于计算机的计算方式: f(x)=sinxx2+4x+3⇒d4fdx4 ...
- (记录)mysql分页查询,参数化过程的坑
在最近的工作中,由于历史遗留,一个分页查询没有参数化,被查出来有sql注入危险,所以对这个查询进行了参数化修改. 一看不知道,看了吓一跳,可能由于种种原因,分页查询sql是在存储过程中拼接出来的,wh ...
- 微信小程序知识集锦
1.自定义属性/获取属性值 自定义属性: <view bindtap='shopPost' data-myid='item.goods_id' ></view> 获取属性: s ...
- 【从翻译mos文章】在oracle db 11gR2版本号被启用 Oracle NUMA 支持
在oracle db 11gR2版本号被启用 Oracle NUMA 支持 参考原始: Enable Oracle NUMA support with Oracle Server Version 11 ...
- 关于 Swift 2.0 - 语言新特性与革新
随着刚刚结束的 WWDC 2015 苹果发布了一系列更新,这其中就包括了令人振奋的 Swift 2.0. 这是对之前语言特性的一次大幅的更新,加入了很多实用和方便的元素,下面我们就一起来看看这次更新都 ...
- WPF 获得DataGridRow和 DataGridCell的方法
原文:WPF 获得DataGridRow和 DataGridCell的方法 原文地址 简介 在WPF中,DataGrid控件并没有提供访问其DataGridRow或者DataGridCell的方法. ...
- x86汇编指令脚本虚拟机
简介 这是一个可以直接解释执行从ida pro里面提取出来的x86汇编代码的虚拟机. 非常精简,整体架构上不能跟那些成熟的虚拟机相比,主要目标是够用.能用.轻量就行,如果觉得代码架构设计的不是很好的话 ...