肇鑫的技术博客

业精于勤,荒于嬉

为什么说只有远程通知才是最吼的!(续)

这篇文章会根据我的体验和理解进行增补和删减

如果是新增,那么内容会直接添加。
如果是修改或删减。我会将原有的段落标记加上删除线。然后再写上新段落。
如果出现多次修改和删减。我会添加版本的提示。如果没有提示,那么相邻的删除线的段落,就是同一个版本的。

简析远程推送服务的解决方案

苹果不承诺远程通知的可靠性。所以远程通知在实际使用中,经常有延迟,甚至丢失的情况。这时,你有两个选择。PushKit或调教苹果的apns服务器。

苹果不承诺远程通知的可靠性。并且由于我们在使用远程通知时,往往会使用第三方的推送服务。因此,一旦通知出现延迟甚至丢失,那么既有可能是苹果的问题,也可能是第三方服务的问题。就目前我自己的感受来说,苹果的服务要比第三方服务更可靠一些。

如果你的程序对于实时性要求较高。那么可以使用收费的第三方服务,这样可以保证你的推送的质量。或者使用自己的推送服务器。更进一步,你还可以使用PushKit

PushKit

PushKit是苹果伴随iOS 8推出的特殊通知,它针对的是一般远程通知的缺点。最初的设计目标是提供给VoIP的app以实时的通知。iOS 9的时候,苹果又增加了对于手表表盘上小部件的推送。

一般远程通知的缺陷

  1. 苹果不保证远程通知一定能到达。苹果会根据它的apns服务器的情况,动态来处理你的推送请求。也就是说,你的请求可能被执行,也可能会延迟,甚至被忽略(忘记)。
  2. 苹果的apns服务器最多只保留最后一条的推送请求。比如用户设备离线的情况下,你发出了多条通知,那么最终用户至多只能收到最后一条。
  3. 如果用户通过呼出任务管理,并且上滑移除app。那么该app的远程推送,将不能唤醒该app到后台,直到用户手动打开该app,或重启手机并解锁进入。
  4. 远程通知注册的token,隔一段时间会自动变化。这时如果还按照旧的申请,就会收不到消息。

苹果的处理方式

  1. 针对问题1。苹果保证PushKit通知会即时到达。看其他人写的评测,基本上延迟只有1秒。因为VoIP是类似打电话的功能,这个延迟高了,服务就没法用了。
  2. 用户设备可以在收到远程通知后,向自己的服务器,苹果称之为Provider,进行反馈。由于通知是即时的,服务器在“向要求苹果apns的服务器发出通知”的命令发出后,如果在特定时间没有收到用户设备的反馈,就可以认定用户的设备是离线的。这之后如果还需要给用户设备发通知,就可以先缓存起来,而不要发送到苹果的apns服务器。服务器可以在确认用户设备启动之后,再一次性将缓存的通知发出,这样,用户就可以得到在设备离线期间缓存的所有信息。
  3. PushKit的通知仍可以唤醒程序。
  4. PushKit的token是不变的。

PushKit的缺点

  • 实现比远程通知更为复杂。除了远程通知的要实现之外,还要向Provider做出反馈。
  • 国内没有现成的第三方服务,需要使用国外的第三方服务。或者自己编写Provider

调教苹果的apns服务器

如果你不想实现PushKit,那么你可以采用下面的比较脏的方式来调教苹果的apns服务器。

我的程序每小时通知一次设备。但是我发现,这个通知有时候会丢失,每天大概会丢个两回左右。

更进一步研究,我发现,如果通知没有及时到达,那么我可以在一段时间之后,补发一个通知。由于我没有实现PushKitProvider服务器不知道上一个通知到达了没有,因此我必须每小时发送两次通知。iOS端如果收到了第一个通知,那么可以做下标记,第二个通知到来时,就直接忽略,不要向Apple Watch传送就可以了。

这个调教的方式的原理是这样的。当apns服务器繁忙时,我猜测苹果采用了一个典型的美国式公平的策略。即大家都丢一些,而不是规定一个资源上限,占用资源多的丢,占用少的不丢。这导致一个现象,就是爱哭的孩子有糖吃。比如我的程序,原本每小时只需要一次推送。但是由于苹果的apns服务器会偶发的抛弃其中的1-2个通知。那么我为了保证通知的必须到达,就需要每小时发两次。实际上这导致苹果apns服务器的负载增加了一倍。但是我没有办法,因为只有这样,才能保证我的程序每小时至少刷新一次。

这个方法相对于PushKit,优点是实现简单。缺点也很明显,不考虑苹果apns的服务器负载增加的损失。只考虑开发者自己这边,最主要的缺点是通知到来的时间不稳定。既可能在第一次的时间到来,也可能是第二次。如果是对于通知到来时间,有特定要求的程序,那就不能用这种方式,而必须使用PushKit

系列文章

为什么说只有远程通知才是最吼的!
为什么说只有远程通知才是最吼的!(续)
为什么说只有远程通知才是最吼的!(续+1)