APNs 推送原理及問題(轉)

在 iOS 平臺上,大部分應用是不容許在後臺運行並鏈接網絡的。在應用沒有被運行的時候,只能經過 Apple Push Notification Service (APNs) 把數據發送到終端用戶。對於互聯網應用,正確高效的使用 APNs 顯然很是重要。html

JPush 爲 iOS、Android 平臺提供了一個統一推送消息的平臺,而對 APNs 接口的封裝管理是其中很是重要的一部分。本文分享一下 JPush 團隊在使用 APNs 過程當中碰到的問題以及咱們的解決辦法,以幫助應用開發者更好的理解 APNs。網絡

Apple 爲應用開發者提供了一個 APNs  推送接口,稱爲 binary interface。app

Binary Interface V1

最第一版本的 binary interface 協議以下圖,這裏咱們稱之爲 v1。ide

Binary Interface V1學習

v1 協議有幾個問題:ui

  1. 消息是否發送成功沒有明確的反饋;spa

  2. 若是一個消息發送失敗,好比由於 deviceToken 不合法,APNs 會在大約 500ms 後斷掉連接,在斷鏈前發送的消息也會發送失敗;.net

  3. 經咱們驗證,feedback service 只有報告應用被卸載後,形成 deviceToken 失效的錯誤。而不會報告 deviceToken 不合法這種類型的推送錯誤。設計

也就是說若是咱們給一批用戶發消息,只要有一個 deviceToken 不合法,將會有可能形成若干個用戶收不到消息。而且沒辦法確認哪些 deviceToken 不合法,哪些 deviceToken 須要被重發。這應該是 APNs 丟消息的一個重要的緣由。htm

Binary Interface V2

通過開發者不斷的向 Apple 反饋這個問題,Apple 終於推出了一個新版本的 binary interface,稱爲 enhanced binary interface,咱們稱這爲 v2。

Binary Interface V2

咱們發現,在 v1 的基礎上增長了兩個字段:

Identifier —— 一個任意的值,用於一條消息的識別。若是發送出現問題,錯誤應答裏會把 Identifier 帶回來。

Expiry —— 離線消息超時的時間,若是爲0或者小於0,APNs 不會保存這條消息。

和 v1 同樣,若是消息發送沒有問題,APNs 不會有任何返回。和 v1 不一樣,而且很重要的改進是,若是發送出現錯誤,v2 會在斷鏈以前返回一個錯誤應答,帶上發消息時的 Identifier 和一個錯誤碼。

error-response packet

根據這個錯誤應答,咱們有機會找到是哪條消息發送出錯,並肯定哪些消息須要被重發。

JPush 的解決辦法

爲了確保每一位用戶都能正確的收到消息,JPush 目前已經放棄 binary interface v1,徹底採用 binary interface v2。(在我寫這篇文章時,發現 Apple 已經把文檔中對 binary interface v1 的描述移除,看來 Apple 也已經放棄 v1)

在系統設計上,咱們爲每個 APNs 連接維護 一個已發送列表,按發送的前後順序排序。若是收到發送錯誤應答,根據返回的 Identifier 找到出錯的消息,從該消息的下一條從新開始發送。

發送隊列

總結

爲了持續提升 JPush 推送服務的質量,咱們團隊作了不少研究和嘗試。APNs 管理模塊咱們最初用 C 語言實現了一個版本,後來以爲用 Erlang 實現可能更方便,因此又從頭開始學習 Erlang 並從新用 Erlang 寫了一個版本,目前使用效果良好。

在 APNs 管理系統改造的過程當中,包括 JPush 的其餘模塊,都大量的使用了開源的模塊或者系統,爲了回饋開源社區,咱們準備把 APNs 管理系統的 Erlang 實現開放源碼,敬請期待。

參考

相關文章
相關標籤/搜索