Apple Push Notification Service 问题小记

我们的产品因为有iOS客户端,所以我们服务器端会通过Apple Push Notification Service来给iOS用户发送通知,前几个月发现有大量的APNS相关的异常,一直忙着弄别的去了没管这个,后来会过头来看,发现APNS在iOS客户端上基本不能用了。

当时试过抓包,发现SSL握手之后,服务器端发送了payload,然后服务器端就立刻关闭TCP连接了,当时比较困惑,猜测有这么几种可能性:
1)APNS协议更新了,老协议停止使用了
2)客户端取到的device token有问题(当时AppStore上上架的app还是好几年前开发的)

然后逐步排除,先是参考Apple的文档把最新的协议实现了,发现最新的协议还提供了Feedback service,觉得挺好的也跟着做了。然后重试,发现依然是服务器直接关闭TCP连接。
那么考虑第二种可能性,将正在开发中的2.0 app用来调试,因为当时还没上架,所以只能让我们的staging server连APNS的Sandbox Gateway,发现可以接收通知,新版本配新协议至少在staging server上是工作正常的,这个不能说明任何问题。

把app上架之后,使用AppStore里下下来的版本连接启用了新APNS协议的产品服务器,发现问题依然重现。Apple的Sandbox Gateway和Production Gateway应该不会有很大的差异,但是Sandbox上可以用而Production完全不可用,当时第一反映是不是IP给封了,然后查看Apple的文档,发现了这么一段话:

Keep your connections with APNs open across multiple notifications; don’t repeatedly open and close connections. APNs treats rapid connection and disconnection as a denial-of-service attack. You should leave a connection open unless you know it will be idle for an extended period of time—for example, if you only send notifications to your users once a day it is ok to use a new connection each day.

当时第一反映就是APNS的服务器可能禁了我们IP,然后搜了好久,在Apple的官方文档里没有看到如何解禁IP的方法。在一边寻找解禁的同时,一边修改服务器端,将以前一个客户端一个APNS SSL Socket的做法改成了共用一个APNS SSL Socket,将改动好后的版本放到产品服务器上后,只有单个APNS连接的实现依然不起作用,难道是Apple没有自动解禁IP的功能?

不过依然没有100%的把握是IP被禁了造成的这个问题,试了一下把产品上的证书放到stage上,让stage上的程序连接APNS的Production Gateway,然后上手机上的app登录我们产品服务器,切换到后台,然后从Xcode里获取到app的Device Token,然后进入我们stage上的后台,让后台根据这个Device Token注册一下,并让stage服务器往APNS的Production Gateway发送一个通知,依然无果。

但是这个证明了肯定不是IP的问题,而唯一的差异就是证书了。那么就很有可能是APNS发现到了DDoS攻击后,禁的是证书,而不是IP。这样就可以解释之前所有的失败了。然后登录到Apple的Member Center,重新生成了一个APNS的证书拿到stage上试了一下,手机终于可以正确的收到通知了,赶紧把新证书换到产品服务器上去,一切就正常了。


Last modified on 2015-01-26