某些設備未收到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 联系我们: