《移动IM开发指南》系列文章将会介绍一个IM APP的方方面面,包括技术选型、登录优化等。此外,本文做者会结合他在网易云信多年iOS IM SDK开发的经验,深度分析实际开发中的各类常见问题。git
推荐阅读github
移动IM开发指南1:如何进行技术选型缓存
移动IM开发指南2:心跳指令详解安全
在移动 IM 模块中,最核心最复杂的模块莫过于登陆模块。一个没有通过很好优化的登陆模块每每耗时久且浪费流量:一次登陆短则数十秒,长则几分钟,同时同步下几百 KB 甚至几M的数据。服务器
一个简单的登陆步骤能够分为以下几步:微信
- 请求 lbs
- 链接 link
- 收发登陆请求
- 同步 IM 数据
而这里的每一步都是有优化的可能性。(事实上下面的不少思路都是普适的,不是只有 IM APP 才用获得)网络
优化 lbs 请求负载均衡
在 PC 时代,咱们每每将请求 lbs 和链接服务器作一个串联,毕竟只有先请求完毕 lbs 才可以拿到真正的 link 服务器地址,从而进行链接操做。在具体操做上,通常 lbs 请求就是一次 HTTP 请求,这里的耗时可想而知。因此一个朴素的优化想法就是从登陆流程中移除这个环节。异步
然而直接粗暴去除 lbs 请求并不可取,若是咱们直接内置域名或 ip,带来最大问题天然是没法作负载均衡。因此更推荐将 lbs 请求异步化:不在登陆时作 lbs 请求,而在网络空闲和发生变化时进行请求并缓存,每次登陆则直接从本地缓存获取 link 地址。ide
DNS 优化
使用 TCP 时不可避免会碰到 DNS 解析的问题,毕竟咱们不可能一直使用 IP 做为服务器地址。在 PC 时代,DNS 解析几乎不费事。但进入无线时代后,DNS 相关问题愈来愈严重。一方面,在移动网络下,DNS 解析速度无比龟速,一次 DNS 解析的时间甚至能遇上一次 TCP 链接的时间,几秒,十几秒,甚至三,四十秒的请求时间都很常见。另外一方面,因为运营商的不做为和做为,移动网络下 DNS 也呈现了解析准确度低和常常被劫持的状态。
针对这些状况能够考虑使用 HTTP DNS,github 也有不少开源的实现,好比HttpDNSLib。而最激进的方法天然是像前面优化 lbs 同样,在个个环节中避免 DNS 解析:
- lbs 返回服务器 ip 而非域名
- 本地缓存 lbs ip 地址备用,请求 lbs 时优先使用 ip 而非域名
这种方式不只能够避免 DNS 请求的耗时,也能够必定程度上规避 DNS 被劫持的问题。而弊端是针对这种状况须要在客户端考虑一系列的其余问题:如何从 ip list 选择有效地址,肯定从新请求时机,负载均衡,节约流量等。
登陆请求
事实上,登陆请求环节其实并无多大的优化空间。一旦你链接上了服务器,接下去要作的事无非是加密当前链接和发送并接收登陆反馈。这两步缺一不可。而如何优化又每每会和具体的业务相关:假如咱们使用相似于 HTTPS 通常的三步协商的加密流程,安全性的确能够获得保证,可是一来一回的次数过多,整个登陆耗时就会增长。取巧的方法天然是将加密和登陆请求合并,而这每每会涉及到对登陆请求的改造。
同步策略优化
登陆完毕后,客户端须要从服务器同步,一个常规的 IM APP 须要同步以下数据:
- 好友列表
- 好友我的信息
- 群组列表
- 群成员列表
- 群成员我的信息
- 离线消息
假设一个用户有 1000 个好友, 20 个 50 人群,平均每一项大约 200 个字节,那么一次全同步大约须要 0.2 * (1000 + 1000 + 20 + 1000 * 2) = 800 KB 的数据,这对于一个移动 IM 是没法接受的,更况且这仍是一个较轻度用户的数据量。
显然全同步是没法接受的,改进的方法天然是按时间戳同步。客户端永远只更新比本地缓存数据新的数据。这是一个常规的优化方向,还有一些根据业务需求能够实施的优化:延迟更新和按需更新。以群成员我的信息为例,其实用户并不关心其实时性,毕竟这些群成员并不必定是用户好友,他们的信息变更彻底能够在用户进行查看时再更新(微信的策略)。而好友我的信息也是同理,对于大部分界面而言,他们只关心用户 Id,头像和昵称这三个基础信息,而一些锦上添花的 Profile 信息彻底能够在用户查看相应界面时进行一次按时间戳的更新。