您好,歡迎來電子發(fā)燒友網(wǎng)! ,新用戶?[免費注冊]

您的位置:電子發(fā)燒友網(wǎng)>源碼下載>通訊/手機編程>

對APNs的正確解讀

大小:0.3 MB 人氣: 2017-09-26 需要積分:1

  反人類的舊APNs協(xié)議設(shè)計

  在介紹新版 APNs 前,讓我們來吐槽下舊的基于二進制的 APNs 協(xié)議設(shè)計是多么反人類:

  在理論上,推送分發(fā)的服務(wù)器要打開一個同 APNs 網(wǎng)關(guān)服務(wù)器的

  連接,并保持這個連接。但在舊的協(xié)議下,APNs 服務(wù)卻不保證 socket 能維持這個連接。如果通道上沒有消息往來,空閑下來到話,socket將被路由掐斷。也就是說:APNs 連接說斷就斷,而你無能為力。有意思的是:在舊的協(xié)議下,如果服務(wù)器響應(yīng)成功的話,你將不會收到任何回應(yīng),但是如果服務(wù)器響應(yīng)失?。ɡ纾褂昧艘粋€非法的 Push token),服務(wù)器將返回了一個錯誤編碼,并關(guān)閉這個socket。最重要的是,你必須重新發(fā)送使用這個無效 token 以后發(fā)送的所有推送(詳情見示意圖)。因此,你可能一直不能確定你的推送是否成功的被 APNs 服務(wù)器接收。

  成功了不響應(yīng),失敗了才響應(yīng),這個是最大的反人類。于是許多開發(fā)者想到了一個很 tricky 的辦法:利用這個“漏洞”,比如在每發(fā)送10條后故意發(fā)送一個錯誤的token,如果APNs有響應(yīng)了,就可以確認 APNs 是處在可用狀態(tài)的,進而確認這10條消息是發(fā)送成功的。如果沒有響應(yīng)就說明可能連接已經(jīng)中斷,那么這10條消息很可能是丟失的,然后做進一步的處理。但代價顯而易見:將導致你們的推送系統(tǒng)性能低下。(本文中所說到“你們的推送系統(tǒng)”,如果是使用的第三方的SDK完成的推送服務(wù),那么就是指SDK提供商所搭建的推送系統(tǒng)。如果是你們公司自己搭建的推送系統(tǒng),那么就是指你們自己的推送系統(tǒng)。)蘋果有一個名為“feedback”的服務(wù),我們可以定時調(diào)用這個服務(wù)來獲取invalid tokens的列表。這個服務(wù)你只要調(diào)用一次就可以獲得所有的invalid tokens 列表。所以,如果一個應(yīng)用使用了很多不同公司的推送SDK,他們將會爭奪資源去輪詢查找invalid tokens列表。invalid token越多,你們的推送系統(tǒng)性能將越低。而且 APNs 只要一發(fā)生錯誤就關(guān)閉這個連接,然后重新連接。也就是“重啟” socket 連接。

  示意圖:

  

  圖中的 PN2 去哪里了?它被放到了 feedback 列表里,等待下次你調(diào)用 feedback 服務(wù),然后重發(fā)。

  為什么Apple要在舊APNs中設(shè)計出“重啟”的策略?為了效率。就像PC機出問題,我們總說“重啟能解決90%的問題”。

  為了理解“重啟”策略,我們可以類比下,熟悉 Erlang/OTP 的朋友可能知道, Erlang/OTP 在處理錯誤方面有獨到之處:監(jiān)督樹(supervision trees)。大致來說,每一個 Erlang 進程都由一個監(jiān)督進程發(fā)起并監(jiān)視。當一個進程遇到了問題的時候,它就會退出。當進程退出的時候,其監(jiān)督進程會將其重啟。

 ?。ㄟ@些監(jiān)督進程由一個引導進程(bootstrap process)發(fā)起,當監(jiān)督進程遇到錯誤的時候,引導進程會將其重啟)

  其思想是,快速的失敗然后重啟比去處理錯誤要快。像這樣的錯誤處理看起來跟直覺相反 —— 當錯誤發(fā)生的時候通過放棄處理來獲得可靠性。但是重啟的確是解決暫時性錯誤的靈丹妙藥。

  這也可能讓你想到 DNS 服務(wù)發(fā)展史:

  DNS 在設(shè)計之初是基于 UDP 的,顯然這樣的設(shè)計不能滿足當今社會的準確性的需求,于是涌現(xiàn)了如 DNSPod 這樣的基于 HTTP 的 DNS 解析服務(wù)。但是當時為什么這樣設(shè)計,實際也很好理解,UDP 效率高,一來一回網(wǎng)絡(luò)上傳輸?shù)闹挥袃蓚€包,而 HTTP則需要三次握手三個包,再一拆包,就需要四個包。這是受限于當時整個社會的帶寬水平較低,而現(xiàn)在沒人會感激 UDP 所節(jié)省的流量,所有人都在詬病DNS污染問題。這樣你也許就理解了,為什么舊的 APNs 設(shè)計如此反人類。這個是必經(jīng)階段。

  那么接下來就讓我們看看Apple為解決這些問題而推出的基于 HTTP/2 的全新 APNs 協(xié)議。

  基于 HTTP/2 的全新 APNs 協(xié)議

  來看下新版的 APNs 的新特性:

  1)Request 和 Response 支持JSON網(wǎng)絡(luò)協(xié)議

  2)APNs支持狀態(tài)碼和返回 error 信息

  APNs推送成功時 Response 將返回狀態(tài)碼200,遠程通知是否發(fā)送成功再也不用靠猜了!

  APNs推送失敗時,Response 將返回 JSON 格式的 Error 信息。

  3)最大推送長度提升到4096字節(jié)(4Kb)

  4)可以通過 “HTTP/2 PING ” 心跳包功能檢測當前 APNs 連接是否可用,并能維持當前長連接。

  5)支持為不同的推送類型定義 “topic” 主題

  6)不同推送類型,只需要一種推送證書 Universal Push Notification Client SSL 證書。

  示意圖:

  對APNs的正確解讀

  其中最大的變化就是基于了 HTTP/2 協(xié)議,采用了長連接設(shè)計,并提供 “HTTP/2 PING ” 心跳包功能檢測、維持當前 APNs 連接,解決了老 APNs 無法維持連接的問題。

  而且新增的狀態(tài)碼特性,也解決了這個問題:無法獲知消息是否成功地從你們的推送系統(tǒng)投遞到了 APNs 上。理論上,你們可以保證消息是100%投遞到了APNs的,因為你可以準確的知道哪條消息到達了APNs,哪些沒到。重發(fā)特定失敗消息成為可能。

  所以上文開頭的吐槽中第一條,有一句是“不到位的”,因為現(xiàn)在SDK的提供商能夠準確地告訴你哪些消息推送到APNs了,哪些沒有。

  順便介紹下 HTTP/2:

  HTTP/2 是 HTTP 協(xié)議發(fā)布后的首個更新,于2015年2月17日被批準。它采用了一系列優(yōu)化技術(shù)來整體提升 HTTP 協(xié)議的傳輸性能,如異步連接復(fù)用、頭壓縮等等,可謂是當前互聯(lián)網(wǎng)應(yīng)用開發(fā)中,網(wǎng)絡(luò)層次架構(gòu)優(yōu)化的首選方案之一。

  Apple 對于 HTTP/2 的態(tài)度也非常積極,2015年5月 HTTP/2 正式發(fā)表后不久,便在緊接著6月召開的WWDC 2015大會中,向全球開發(fā)者宣布,iOS 9 開始支持HTTP/2。

  而且如果我們要使用 HTTP/2,那么在網(wǎng)絡(luò)庫的選擇上必然要使用 NSURLSession。

  我們都知道 HTTP/2 是復(fù)用 TCP 管道連接的,而且 HTTP/2 也以高復(fù)用著稱,這也使新的 APNs 協(xié)議更加高性能。(題外話:這點也同樣體現(xiàn)在 NSURLSession 底層對于每個 session 是對多個 task 進行連接的復(fù)用。)

  Universal Push Notification Client SSL 證書

  在開發(fā)中,往往一條內(nèi)容,需要向多個終端進行推送,終端有:iOS、tvOS、 and OS X devices, 和借助iOS來實現(xiàn)推送的 Apple Watch。在以往的開發(fā)中,不同的推送,需要配置不同的推送證書:我們需要配置:dev證書、prod證書、VOIP證書、等等。而從2015年12月17日起,只使用一種證書就可以了,不再需要那么多證書,這種證書就叫做Universal Push Notification Client SSL 證書(下文統(tǒng)一簡稱:Universal推送證書)。

  改進了,但仍需改進。還是有坑

  APNs的確改進來不少,但仍有需要改進對地方。還是有坑:

  除了獲取TLS證書比較復(fù)雜未解決外,還有一些坑:

非常好我支持^.^

(0) 0%

不好我反對

(0) 0%

      發(fā)表評論

      用戶評論
      評價:好評中評差評

      發(fā)表評論,獲取積分! 請遵守相關(guān)規(guī)定!

      ?