# iOS 隔了较久时间推送变得缓慢



![](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/442e4085cf4b8f62c7ad359343c5f155_hd.png)



这个图是重点，描述了真实消息推送的过程，App开发者或者第三方推送平台的服务器\(图例中的Provider\)向APNs发起推送指令的请求，**推送指令包含了要下发设备的device-token和要下发的内容payload两部分**，由APNs根据device-token\(device-token是APNs生成颁发的\)将payload下发到设备上，再由设备路由给具体的App。我们这里只关注第一步Provider到APNs的过程，即Provider的服务器和APNs的服务器通信的过程。APNs要求Provider首先与APNs建立一条长连接，Provider通过长连接可以将单个或者一批device-token发送给APNs，这个过程中，只要有一个device-token是不合法的\(错误或者失效\)，那么APNs就会主动断掉Provider到APNs的长连接，Provider探测到连接断掉之后，需要重新建立连接，跳过上次失败的device-token，从下一个device-token接着发送。这个过程循环往复，直至将本次要发送的所有的device-token都推送到APNs，那么这次推送任务就算完成了。剩下的工作就是APNs将消息下发到具体设备了，APNs将消息下发给设备这个过程，不管是App开发者直接和APNs打交道、亦或是第三方推送服务器和APNs打交道，我们都是无法控制的了，所以推送的重点就是图例中的第一步Provider到APNs之间的通信了。

接下来我们回到问题，就是为什么隔了很久之后再去做推送，发送过程会变得非常慢。其实经过上面的解释，大家就应该能把原因猜的差不多了，就是因为长时间不发送的话，会有很多设备上的device-token已经无效了，比如设备卸载了App，或者系统版本升级过导致device-token变化了，或者是其它导致APNs认为device-token不合法的原因。总之，时间长了，不合法的device-token就会变多，在上面的章节中也提到，Provider和APNs的服务器建立长连接进行消息发送时，如果碰到了不合法的device-token，APNs就会断掉长连接，需要Provider重新建立连接。失效的device-token多了，那么断掉连接-重新连接的次数就会增多，每次重新连接都需要耗费时间，甚至如果频繁的断掉-重连APNs，有时候会被APNs认为是一种DoS攻击\(APNs官网这么解释，但是具体判定的算法没有透露\)，会导致短时间内APNs拒绝Provider的连接，这种情况下，不管是App开发者自己直接和APNs打交道，还是第三方推送平台和APNs打交道，碰到这种情况都是无能为力的。 只能被动的接受“断掉-重连”的工作方式，因此整个发送过程会特别缓慢。 所以总结下来，长时间不发送消息，再次发送的时候，必然会出现推送缓慢的情况，原因就是无效的device-token越来越多，导致不断的“断开-重连”。所以在本文开头的时候，就提到过如果App开发者亲自使用过APNs服务的话，对这种现象必定是非常熟悉了，也会见怪不怪了。 如果是两次发送任务之间隔得时间不是太长，两次发送期间失效device-token不是那么多的时候，速度还是比较快的。

那么既然失效的device-token是导致发送变慢的主要原因，那么开发者朋友们肯定会想，能不能提前判断出失效的device-token，直接从发送列表中剔除掉这些失效的token。其实APNs是提供这样的feedback接口的，调用这个接口会得到一批失效的device-token列表。那么是不是在一次发送之前去调用一下这个接口，获取到无效的device-token，在发送的过程中剔除掉这些无效的device-token就能加快发送速度呢？ 其实不然，因为feedback接口是一个后验的接口，即只有一次推送任务结束之后，APNs才会把该次失效的device-token更新到feedback接口的返回结果里面。如果你在一次推送任务前调用feedback接口，那么得到的失效device-token是基于上一次推送任务的结果的，两次推送任务之间发生的失效的device-token，是无法提前获取到的，只能等当次推送任务结束之后，才可以去获取新的失效token列表。

问题到这里就解释清楚了，那么碰到这种情况，我们该如何提升发送速度呢？ 这里我们给大家讲讲友盟推送平台针对这种情况做的一些优化，相比App开发者直接连接APNs做推送，还是有一定的优势:\) 解决方法很简单，就是友盟有很多台连接APNs的服务器，每个服务器我们又会开很多个线程去和APNs做连接，所以在并发度上会有较大的优势。所以针对一次发送任务，使用友盟平台做推送，速度肯定会比自己直接连接APNs有优势，这个也是不少开发者放弃了直接和APNs打交道，而是选择友盟推送来实现iOS推送的原因之一。

