某些设备未收到Apple推送通知

我正在使用Apples iOS增强通知格式批量发送推送通知,并使用本文中描述的PHP解决方案: https : //stackoverflow.com/a/10059000/300129

此时的经验是,当我发送推送通知时,某些设备正在接收消息,而某些设备则没有。 结果不一致。 有时设备X会收到通知,有时设备X不会收到通知。 我正在记录所有内容,但我没有得到任何错误响应。

对正在发生的事情的任何想法都会非常有帮助。

您链接的答案中的解决方案存在问题。 它会尝试在每条消息发送后读取错误响应,但读取会立即返回,并且不会等待响应变为可用。 虽然这比在每条消息之后等待X mili-seconds的潜在错误响应更有效,但您可能会错过错误响应,Apple可能会在不知道发生任何错误的情况下断开连接。

虽然我不能给你代码来解决你的问题,但我会给你一些建议。

这是您应该使用的逻辑(根据Apple),但我没有设法让它可靠地工作(至少在我的Java实现中没有):

推送通知吞吐量和错误检查

如果您发现吞吐量低于每秒9,000个通知,则您的服务器可能会受益于改进的error handling逻辑。

以下是使用增强型二进制接口时如何检查错误。 继续写入,直到写入失败。 如果流已准备好再次写入,请重新发送通知并继续。 如果流尚未准备好写入,请查看该流是否可供读取。

如果是,请从流中读取所有可用内容。 如果返回零字节,则由于诸如无效命令字节或其他解析错误之类的错误而关闭连接。 如果你得到六个字节,这是一个错误响应,你可以检查响应代码和导致错误的通知的ID。 您需要再次发送该通知之后的每个通知。

一旦发送完所有内容,请最后一次检查是否有错误响应。

由于正常的延迟,丢弃的连接可能需要一段时间才能从APN返回到服务器。 由于连接被丢弃,在写入失败之前可以发送超过500个通知。 大约1,700个通知写入可能因为管道已满而失败,因此只有在流可以再次写入时才重试。

现在,这里的权衡变得有趣。 您可以在每次写入后检查错误响应,并立即捕获错误。 但这会导致发送一批通知所需的时间大幅增加。

如果您正确捕获设备令牌并将它们发送到正确的环境,则设备令牌几乎都应该有效。 因此,优化假设失败是很少见的。 如果在检查错误响应之前等待写入失败或批处理完成,即使计算再次发送已删除通知的时间,您也会获得更好的性能。

这些都不是APN特有的,它适用于大多数套接字级编程。

如果您选择的开发工具支持multithreading或进程间通信,您可以让线程或进程始终等待错误响应,并让主发送线程或进程知道何时应该放弃并重试。

这取自Apple的技术说明: 推送通知疑难解答 。

我不知道你在PHP中如何检测到写入失败,但是当它发生时,你应该再次尝试写失败的通知,如果再次失败,请尝试读取错误响应并关闭连接。

如果您设法读取错误响应,您将知道哪个通知失败并且您将知道错误类型(最可能的错误是8 – 无效的设备令牌)。 您提到的答案中的代码在识别出错误后没有做任何事情。 如果在写完100条消息后您收到第80条消息的错误响应,则必须重新发送消息81到100,因为Apple从未收到过消息。 在我的情况下(Java服务器),我并不总是设法读取错误响应(有时我尝试从套接字读取响应时出错)。 在这种情况下,我只能继续发送下一个通知(并且无法知道Apple实际收到了哪些通知)。 这就是为什么保持数据库清除无效令牌很重要的原因。

如果您保持数据库清洁(即只存储Apple发送给您的应用程序的设备令牌,并且它们都属于同一推送环境 – 沙箱或生产),您不应该遇到任何无效的设备令牌。

在Java中实现推送通知服务器端时,我遇到了类似的问题。 我无法可靠地获得Apple返回的所有错误响应。

我发现在Java中有一种方法可以禁用TCP Nagle算法,这会导致多个消息在批量发送到Apple之前缓冲。 虽然Apple鼓励我们使用Nagle的算法(出于性能原因),但我发现当我禁用它然后在发送给他们的每条消息后尝试读取Apple的响应时,我设法收到100%的错误响应(I通过编写模拟APNS服务器的过程来validation它。

通过禁用Nagle算法并逐个发送通知,慢慢地尝试在每条消息之后读取错误响应,您可以在数据库中找到所有无效令牌并将其删除。 一旦您知道您的数据库是干净的,您就可以启用Nagle的算法并快速恢复发送通知,而无需阅读Apple的错误响应。 然后,每当您在向套接字写入消息时收到错误,您只需创建一个新套接字并重试仅发送最后一条消息。

即使APNS服务器接受了推送通知,也无法保证实际发送推送通知

就您的服务器而言,推送通知是偶然的; 在将通知发送到APNS后,无法确定通知的状态。 交货时间也可能不同,从几秒到半小时。
此外,用户的iPhone可能无法始终接收推送通知。 它们可能位于WiFi网络上 ,因为所需的端口被阻止,因此无法与APNS建立连接。 或者手机可以关闭。

APNS将尝试在重新联机时提供该设备收到的最后通知 ,但它只会在有限的时间内尝试。 一旦超时,推送通知将永远丢失!

我在几个应用程序中也遇到过这个问题。 某些设备未收到推送通知的原因可能是:

  • 使用沙盒APNS服务器生成APNS证书。 – >请检查一下
  • 设备上安装了开发和生产临时配置文件。 – >删除临时,然后你必须等待至少24小时,以便苹果也从其服务器中删除设备令牌。

就我而言,在开发过程中,一些APN未在一台设备中接收(我正在使用PushMeBaby进行测试)。

我从我的设备中删除了与我的项目相关的所有以前的配置文件,从那时起一切都很顺利。 为此,请转到“设置”>“配置文件”。

也许我与配置文件存在某种冲突,因为我正在处理的项目已经改变了捆绑包ID和配置文件。