相信大家在使用iPhone版微信的时候都会有这样的经历,微信已经处于关闭状态了(后台进程运行一段时间就被系统杀掉),这时候我们收到了一个消息提醒,打开微信应用,微信显示“连接中…”和“收取中…”,然后再次显示一次刚才系统推送给我的消息通知。对这个现象比较好奇,于是去知乎上查一下资料,发现知乎上的热心人还真多,看了大家的回答之后,总结如下:
[之所以去知乎查看技术问题,因为我并非技术人员,而知乎上很多开发人员是会用通俗易懂的方式解释好技术问题的,因为里面有不少大牛。]
先介绍一下两个重要的消息推送服务:
iOS 的推送:Apple 官方的 APNs (Apple Push Notification service)。
Android 的推送:Google 官方的 GCM (Google Cloud Messaging)。
其实两个推送服务的机制是比较接近的,以苹果为例,用一个图示表示如下:
采用 APNs 或者 GCM 进行消息推送,消息都会经由苹果或者谷歌的服务器,然后再到用户设备上,这样做的好处主要有以下几点:
1)省电
这个是最直观的体验。由于这两套推送机制都是用户设备和苹果或谷歌的服务器保持一个长连接,而这个长连接是几乎不会耗损多少电量的,采用统一的连接来接收手机上所有应用的通知消息,耗电量少是显而易见的。
由于苹果采用封闭的策略,因此所有第三方应用都必须采取这种推送方式,因此iPhone设备即使电池电量比Android少也更耐用。但由于国内众所周知的原因,Google 服务的稳定性大受考验,而且 Google 对第三方应用推行 GCM 方式并不是强制性的,因此国内的应用开发者几乎都单独在后台常驻一个进程,来专门处理消息推送。
2)开发简单
这个是对应用开发者来说的,一般不使用上述的 APNs 或者 GCM 推送机制,就需要自己搭建一条推送服务,可以采用别人开发的成熟协议,或者自己单独开发(如腾讯),这对于开发者来说还是有门槛的。
3)利于统一管理
采用统一的方式来处理就使得系统可以更高效,不会出现多应用同时处理消息卡顿的情况。
当然坏处的话,一个就是稳定性和实效性依赖于苹果或者谷歌的消息服务器,当然这种机制目前正常情况下都能做到5s以内的延迟。如果是第三方应用单独放置一个常驻进程处理,延迟一般在1s内,可以忽略不计。
以上就是两种常见的消息推送机制。但还有一个情况没有解释,为什么我们打开iPhone应用(如微信),应用还要再次和第三方服务器连接一次,再取回一次消息?
这个可以解释为,当应用处于后台关闭状态时,由iOS系统推送一个消息通知给我们。当我们打开应用后,我们的设备就直接和第三方应用的消息服务器通信了,不需要再经由苹果消息服务器传递。
但为了保证消息传递的完整性,刚才系统推送的消息并没有在应用里面显示,所以应用再与第三方服务器建立连接后,再重新把刚才那条消息取回来,这就造成了系统通知一次消息,应用打开后再显示一次消息。当然这种做法可能在使用体验上有些许瑕疵(也许强迫症患者会这么认为吧),但消息的完整性是必须要保证的。
苹果设备统一采用 APNs 推送机制,至少很省电,而安卓设备几乎每个应用都单独设置一个常驻进程来收发消息,造成的情况是,安卓设备将会非常耗电(即使你不使用,后台却同时开着那么多进程),一方面是由于谷歌服务不稳定造成的,但更重要的是,国内开发者都是自私的,只管自己的应用功能正常,而不会顾用户的手机电池会不会耐用。苹果的推送机制别无选择,但安卓系统在国内是存在稳定的推送服务提供商的,一旦采用也能达到iOS设备的效果,但几乎很少开发者会采用。
另外要穿插一个小插曲就是,微信曾经出现过大范围的宕机情况,消息收发出现严重延迟,实际上是网络服务提供方(如移动、联通、电信)在网络上捣鬼,导致消息传递出现大范围延迟。身处国内,即使强大如腾讯,也要对三大运营商忌惮三分啊!当时明明对运营商暗中使坏切齿痛恨,但仍然咬牙向外部宣称“这是由我们的技术故障造成的……”,当时好像还找了个特别无厘头的解释——施工被挖断光缆。好吧,QQ都活了15年,容灾备份机制会没有,怎么可能出现那么严重的事故呢?!