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

Chr*_*ris 8 php iphone apple-push-notifications ios apns-php

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

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

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

小智 6

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

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

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

  • 我知道这是现实,但我不认为我们因Apple交付失败而遭受损失.相同的设备将接收通过不同脚本发送的100%的消息,因此可能是发送批量消息而不是发送个性化消息的结果. (2认同)

Era*_*ran 0

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

虽然我无法为您提供代码来解决您的问题,但我可以给您一些建议。

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

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

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

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

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

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

由于正常延迟,断开的连接可能需要一段时间才能从 APN 回到您的服务器。在写入因连接断开而失败之前,可能会发送超过 500 个通知。大约 1,700 个通知写入可能会因为管道已满而失败,因此在这种情况下,一旦流准备好再次写入,只需重试。

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

如果您正确捕获了设备令牌并将它们发送到正确的环境,那么设备令牌几乎都应该是有效的。因此,假设故障很少发生,那么进行优化是有意义的。如果您等待写入失败或批处理完成后再检查错误响应,甚至计算再次发送丢弃的通知的时间,您将获得更好的性能。

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

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

这取自 Apple 的技术说明:推送通知故障排除

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

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

如果您保持数据库干净(即仅在其中存储由 Apple 发送到您的应用程序的设备令牌,并且所有这些令牌都属于同一推送环境 - 无论是沙箱还是生产环境),您不应该遇到任何无效的设备令牌。

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

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

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