对于移动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推送保障及网络优化详解(二):如何做长连接加推送组合方案的更多相关文章

  1. IM推送保障及网络优化详解(一):如何实现不影响用户体验的后台保活

    对于移动APP来说,IM功能正变得越来越重要,它能够创建起人与人之间的连接.社交类产品中,用户与用户之间的沟通可以产生出更好的用户粘性. 在复杂的 Android 生态环境下,多种因素都会造成消息推送 ...

  2. Comet技术详解:基于HTTP长连接的Web端实时通信技术

    前言 一般来说,Web端即时通讯技术因受限于浏览器的设计限制,一直以来实现起来并不容易,主流的Web端即时通讯方案大致有4种:传统Ajax短轮询.Comet技术.WebSocket技术.SSE(Ser ...

  3. P2P技术详解(二):P2P中的NAT穿越(打洞)方案详解

    1.内容概述 P2P即点对点通信,或称为对等联网,与传统的服务器客户端模式(如下图"P2P结构模型"所示)有着明显的区别,在即时通讯方案中应用广泛(比如IM应用中的实时音视频通信. ...

  4. .NET DLL 保护措施详解(二)关于性能的测试

    先说结果: 加了缓存的结果与C#原生代码差异不大了 我对三种方式进行了测试: 第一种,每次调用均动态编译 第二种,缓存编译好的对象 第三种,直接调用原生C#代码 .net dll保护系列 ------ ...

  5. PopUpWindow使用详解(二)——进阶及答疑

      相关文章:1.<PopUpWindow使用详解(一)——基本使用>2.<PopUpWindow使用详解(二)——进阶及答疑> 上篇为大家基本讲述了有关PopupWindow ...

  6. Android 布局学习之——Layout(布局)详解二(常见布局和布局参数)

    [Android布局学习系列]   1.Android 布局学习之——Layout(布局)详解一   2.Android 布局学习之——Layout(布局)详解二(常见布局和布局参数)   3.And ...

  7. logback -- 配置详解 -- 二 -- <appender>

    附: logback.xml实例 logback -- 配置详解 -- 一 -- <configuration>及子节点 logback -- 配置详解 -- 二 -- <appen ...

  8. 爬虫入门之urllib库详解(二)

    爬虫入门之urllib库详解(二) 1 urllib模块 urllib模块是一个运用于URL的包 urllib.request用于访问和读取URLS urllib.error包括了所有urllib.r ...

  9. phpExcel常用方法详解【附有php导出excel加超级链接】

    phpExcel常用方法详解[附有php导出excel加超级链接] 发表于4年前(-- :) 阅读() | 评论() 0人收藏此文章, 我要收藏 赞0 http://www.codeplex.com/ ...

随机推荐

  1. dos命令查看端口状态

    netstat 显示协议统计信息和当前 TCP/IP 网络连接. NETSTAT [-a] [-b] [-e] [-n] [-o] [-p proto] [-r] [-s] [-v] [interva ...

  2. codeforces Round #259(div2) D解决报告

    D. Little Pony and Harmony Chest time limit per test 4 seconds memory limit per test 256 megabytes i ...

  3. Android面HTTP协议发送get要求

    /** * 采纳get办法要求 * * @param username * @param password * @return null表示求得的路径有问题,text返回请求得到的数据 */ publ ...

  4. 开源mvcpager分页控件分页实例

    最近MVC需要用到分页,然后在网上找了一圈,发现一个很好用的分页控件,在此要感谢作者的辛勤劳动. 下载Pager 这个分页控件也有Asp.net的支持,需要的去看看作者的主页 webdiyer 先看看 ...

  5. 在 Swift 中实现单例方法

    我们通常在进行开发的时候,会用到一个叫做 单例模式 的东西.相信大家也都对这种模式非常熟悉了.而且单例的使用在平时的开发中也非常频繁. 比如我们常用到的 NSUserDefaults.standard ...

  6. android反射组件 (一个)java 它们的定义annotation基础知识

    它们的定义annotation它由三部分组成: 它们的定义annotation.使用annotation班.annotation的处理方法. 一.自己定义annotation  元注解包含下面: 1) ...

  7. 属性更改通知(INotifyPropertyChanged)——针对ObservableCollection

    问题 在开发webform中,wpf中的ObservableCollection<T>,MSDN中说,在添加项,移除项时此集合通知控件,我们知道对一个集合的操作是CURD但是恰恰没有Upd ...

  8. Boost总结汇总

    从开始接触Boost已经有好几年了,而对它的掌握却难言熟悉,有对它部分的源代码的剖析也是蜻蜓点水.有时间一点点梳理一下吧. 1. 概述 [Boost]C++ Boost库简介[Boost]C++ Bo ...

  9. QML中文件的加载(三种方法)

    在这里小小总结一下QML文件中如何加载QML文件与JavaScript文件. 1.QML文件中加载JavaScript文件 语法: import <ModuleIdentifier> &l ...

  10. 2018-4-25 1.如何在GitHub上新建一个新的项目并下载该项目及如何提交新的文件