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

[英]Some Devices Not Receiving Apple Push Notifications


I am using Apples iOS Enhanced Notification Format to send push notification in bulk, and using the PHP solution described in this post: https://stackoverflow.com/a/10059000/300129

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

The experience at this point is that when I send a push notification, some devices are receiving the message and some devices are not. The results are inconsistent. Sometimes device X will receive a notification and sometimes device X will not. I am logging everything and I am not getting any error responses.

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

Any thoughts about what is happening would be very helpful.

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

4 个解决方案

#1


0  

The solution in the answer you linked to has a problem. It attemps to read the error response after each message is sent, but the read returns immediately and doesn't wait for a response to become available. While this is more efficient than waiting for a potential error response for X mili-seconds after each message, you might miss the error response and the connection may be dropped by Apple without you knowing any error occured.

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

While I can't give you code to solve your problem, I get give you some advice.

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

Here's the logic you should use (according to Apple), but I haven't managed to make it work reliably (at least not in my Java implementation):

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

Push Notification Throughput and Error Checking

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

If you're seeing throughput lower than 9,000 notifications per second, your server might benefit from improved error handling logic.

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

Here's how to check for errors when using the enhanced binary interface. Keep writing until a write fails. If the stream is ready for writing again, resend the notification and keep going. If the stream isn't ready for writing, see if the stream is available for reading.

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

If it is, read everything available from the stream. If you get zero bytes back, the connection was closed because of an error such as an invalid command byte or other parsing error. If you get six bytes back, that's an error response that you can check for the response code and the ID of the notification that caused the error. You'll need to send every notification following that one again.

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

Once everything has been sent, do one last check for an error response.

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

It can take a while for the dropped connection to make its way from APNs back to your server just because of normal latency. It's possible to send over 500 notifications before a write fails because of the connection being dropped. Around 1,700 notifications writes can fail just because the pipe is full, so just retry in that case once the stream is ready for writing again.

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

Now, here's where the tradeoffs get interesting. You can check for an error response after every write, and you'll catch the error right away. But this causes a huge increase in the time it takes to send a batch of notifications.

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

Device tokens should almost all be valid if you've captured them correctly and you're sending them to the correct environment. So it makes sense to optimize assuming failures will be rare. You'll get way better performance if you wait for write to fail or the batch to complete before checking for an error response, even counting the time to send the dropped notifications again.

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

None of this is really specific to APNs, it applies to most socket-level programming.

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

If your development tool of choice supports multiple threads or interprocess communication, you could have a thread or process waiting for an error response all the time and let the main sending thread or process know when it should give up and retry.

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

This is taken from Apple's Tech Note: Troubleshooting Push Notifications.

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

I don't know how you detect in PHP that the write failed, but when it does, you should attempt to write the failed notification once again, and if it fails again, try to read the error response and close the connection.

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

If you manage to read the error response, you will know which notification failed and you'll know the error type (the most likely error is 8 - invalid device token). The code in the answer you referred to doesn't do anything after identifying that error. If after writing 100 messages you get an error response for the 80th message, you must resend messages 81 to 100, since Apple never received them. In my case (Java server), I don't always manage to read the error response (sometimes I get an error when trying to read the response from the socket). In that case I can only move on an send the next notifications (and have no way of knowing which notifications were actually received by Apple). That's why it's important to keep your database clean of invalid tokens.

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

If you keep your database clean (i.e. store in it only device tokens that were sent to your App by Apple, and all of them belong to the same push environment - either sandbox or production), you shouldn't encounter any invalid device tokens.

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

I encountered a similar problem to yours when implementing the push notification server side in Java. I couldn't reliably get all the error responses returned by Apple.

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

I found that in Java there's a way to disable the TCP Nagle's algorithm, which causes the buffering of multiple messages before sending them in a batch to Apple. Though Apple encourages us to use Nagle's algorithm (for performance reasons), I found that when I disable it and then try to read the response from Apple after each message I send to them, I manage to receive 100% of the error responses (I verified it by writing a process that simulated the APNS server).

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

By disabling Nagle's algorithm and sending the notifications one by one, slowly, and atempting to read the error response after each message, you can locate all the invalid tokens in your DB and remove them. Once you know your DB is clean you can enable Nagle's algorithm and resume sending notifications quickly without bothering to read the error responses from Apple. Then, whenever you get an error while writing a message to the socket, you can simply create a new socket and retry sending only the last message.

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

#2


6  

There is no guarantee that push notifications will actually be delivered, even if the APNS server accepted them.

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

As far as your server is concerned, push notifications are fire-and-forget; there is no way to find out what the status of a notification is after you’ve sent it to APNS. The delivery time may also vary, from seconds up to half an hour.
Also, the user’s iPhone may not be able to receive push notifications all the time. They could be on a WiFi network that does not allow connections to be made to APNS because the required ports are blocked. Or the phone could be turned off.

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

APNS will try to deliver the last notification it received for that device when it comes back online, but it will only try for a limited time. Once it times out, the push notification will be lost forever!

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

#3


0  

I have also experienced this problem in my several application. The reason of some devices that are not receiving the push notifications can be:

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

  • Using sandbox APNS server with production APNS certificate. -> Please check it
  • 使用沙盒APNS服务器生成APNS证书。 - >请检查一下

  • Both development and production provisional profiles installed on device. -> Remove both provisional and then you have to wait for atleast 24hr so that apple also remove the device token from its server.
  • 设备上安装了开发和生产临时配置文件。 - >删除临时,然后你必须等待至少24小时,以便苹果也从其服务器中删除设备令牌。

#4


0  

In my case, during development, some APNs where not being received in one device (I was testing with PushMeBaby).

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

I removed from my device all previous provisioning profiles related to my project, and from that moment everything went fine. To do that go to Settings > Profiles.

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

Maybe I had some kind of conflict with profiles since the project I am working on has changed the bundle id and the provisioning profiles since along the way.

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


注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2014/02/10/bf1ec518183541ee19d1715523eb4fa2.html



 
  © 2014-2022 ITdaan.com 联系我们: