你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> 國內90%以上的 iOS 開發者,對 APNs 的認識都是錯的

國內90%以上的 iOS 開發者,對 APNs 的認識都是錯的

編輯:IOS開發基礎

142975401786686550.jpg

本文為投稿文章,作者:iOS程序犭袁 (博客)

前言:

APNs 協議在近兩年的 WWDC 上改過兩次,2015年12月17日更是推出了革命性的新特性。但在國內傳播的博客、面試題裡關於APNs的答案全都是舊的、錯的。

正文:

對 APNs 的吐槽

APNs 是 Apple Push Notification service 的簡稱(注意 APNs 的大小寫, s不需要大寫)。

以下是我收集的一些關於 APNs 的吐槽,你先看下哪些吐槽比較“到位”:

未標題-1.jpg

答案會穿插在下文中。

APNs新聞

2014年6月份WWDC搭載iOS8及以上系統的iOS設備,能夠接收的最大playload大小提升到2KB。低於iOS8的設備以及OS X設備維持256字節。參考文檔:What's New in Notifications - WWDC 2014 - Session 713 - iOS

224803-6d79766372a5b57e.png

2015年6月份WWDC宣布將在不久的將來發布 “基於 HTTP/2 的全新 APNs 協議”,並在大會上發布了僅僅支持測試證書的版本。參考文檔:What's New in Notifications - WWDC 2015 - Session 720 - iOS, OS X 

224803-621bb038574e9a0a.jpg

2015年12月17日起,發布 “基於 HTTP/2 的全新 APNs 協議”,iOS 系統以及 OS X 系統,統一將最大 playload 大小提升到4KB。參考文檔:Apple Push Notification Service Update 12-17 2015

新舊 APNs 協議工作示意圖對比

未標題-1.jpg

接下來我們分別對新舊協議進行一下介紹:

反人類的舊APNs協議設計

在介紹新版 APNs 前,讓我們來吐槽下舊的基於二進制的 APNs 協議設計是多麼反人類:

在理論上,推送分發的服務器要打開一個同 APNs 網關服務器的

連接,並保持這個連接。但在舊的協議下,APNs 服務卻不保證 socket 能維持這個連接。如果通道上沒有消息往來,空閒下來到話,socket將被路由掐斷。也就是說:APNs 連接說斷就斷,而你無能為力。有意思的是:在舊的協議下,如果服務器響應成功的話,你將不會收到任何回應,但是如果服務器響應失敗(例如,使用了一個非法的 Push token),服務器將返回了一個錯誤編碼,並關閉這個socket。最重要的是,你必須重新發送使用這個無效 token 以後發送的所有推送(詳情見示意圖)。因此,你可能一直不能確定你的推送是否成功的被 APNs 服務器接收。

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

示意圖:

224803-9a59449a57ee0e4b.jpg

圖中的 PN2 去哪裡了?它被放到了 feedback 列表裡,等待下次你調用 feedback 服務,然後重發。

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

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

(這些監督進程由一個引導進程(bootstrap process)發起,當監督進程遇到錯誤的時候,引導進程會將其重啟)

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

這也可能讓你想到 DNS 服務發展史:

DNS 在設計之初是基於 UDP 的,顯然這樣的設計不能滿足當今社會的准確性的需求,於是湧現了如 DNSPod 這樣的基於 HTTP 的 DNS 解析服務。但是當時為什麼這樣設計,實際也很好理解,UDP 效率高,一來一回網絡上傳輸的只有兩個包,而 HTTP則需要三次握手三個包,再一拆包,就需要四個包。這是受限於當時整個社會的帶寬水平較低,而現在沒人會感激 UDP 所節省的流量,所有人都在诟病DNS污染問題。這樣你也許就理解了,為什麼舊的 APNs 設計如此反人類。這個是必經階段。

那麼接下來就讓我們看看Apple為解決這些問題而推出的基於 HTTP/2 的全新 APNs 協議。

基於 HTTP/2 的全新 APNs 協議

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

1)Request 和 Response 支持JSON網絡協議

2)APNs支持狀態碼和返回 error 信息

  • APNs推送成功時 Response 將返回狀態碼200,遠程通知是否發送成功再也不用靠猜了!

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

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

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

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

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

示意圖:

224803-5f8792bc600b0d02-(1).jpg

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

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

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

順便介紹下 HTTP/2:

HTTP/2 是 HTTP 協議發布後的首個更新,於2015年2月17日被批准。它采用了一系列優化技術來整體提升 HTTP 協議的傳輸性能,如異步連接復用、頭壓縮等等,可謂是當前互聯網應用開發中,網絡層次架構優化的首選方案之一。

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

而且如果我們要使用 HTTP/2,那麼在網絡庫的選擇上必然要使用 NSURLSession。

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

Universal Push Notification Client SSL 證書

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

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

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

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

文章開頭提到過以下這種情況:

224803-27da8a6744d90831.jpg

很遺憾的告訴你,你的吐槽是“到位的”:你以後還得忍受這種反人類的設計。

這中間發生了什麼?

當 APNs 向你發送了4條推送,但是你的設備網絡狀況不好,在 APNs 那裡下線了,這時 APNs 到你的手機的鏈路上有4條任務堆積,APNs 的處理方式是,只保留最後一條消息推送給你,然後告知你推送數。那麼其他三條消息呢?會被APNs丟棄。

有一些 App 的 IM 功能沒有維持長連接,是完全通過推送來實現到,通常情況下,這些 App 也已經考慮到了這種丟推送的情況,這些 App 的做法都是,每次收到推送之後,然後向自己的服務器查詢當前用戶的未讀消息。但是APNs也同樣無法保證這四條推送能至少有一條到達你的 App。很遺憾的告訴這些App,這次的更新對你們所遭受對這些坑,沒有改善。

為什麼這麼設計?APNs的存儲-轉發能力太弱,大量的消息存儲和轉發將消耗Apple服務器的資源,可能是出於存儲成本考慮,也可能是因為 Apple 轉發能力太弱。總之結果就是 APNs 從來不保證消息的達到率。並且設備上線之後也不會向服務器上傳信息。

所以上文開頭的吐槽中第一條,也有一句是“到位的”,因為現在SDK的提供商依然無法保證,消息推到了 APNs,APNs能推到 App 那裡。

但Google Cloud Messaging就有這些特性。而且 GCM 現在也支持iOS設備了,那麼 APNs 和 GCM 現在就形成了競爭關系。讓我共同期待 APNs 在2016年6月的 WWDC 的能有新的改進吧。

對App開發的影響

想使用新協議,如果你用的第三方推送,這裡最明顯的操作,就是你必須更新到支持新協議的SDK版本。因為新協議需要 SDK 上傳你 app 的 bundle id ,生成各個平台推送用的 topic。如果你們自己搭建的服務,則需要你自己上傳。老協議不用上傳。

新 APNs 支持 iOS6 等全版本推送內容達4096字節,舊 APNs 是14年6月之前只支持256字節,在此之後支持 iOS8 以上2048字節。以前受限於推送字節,比如推文章 url,開發者選擇超出256後推送id,甚至不判斷直接推 id,接收後再請求完整 url。一旦請求錯誤,推送內容可能丟失。現在可以避免了。

如何創建 Universal Push Notification Client SSL 證書

現在你知道什麼是 Universal Push Notification Client SSL 證書了,那麼如何創建它?

12_ios_apns_certificate_2_2x.jpg

圖中其他方式,就叫做非 Universal 方式(下文簡稱:非 Universal 推送證書):

224803-b0f56f0c5bb3330a.jpg

這裡也推薦使用 Universal 推送證書來進行推送服務。詳細的創建步驟如下所示:

  • 前往蘋果開發者中心進行登錄,並點擊 “Certificates, Identifiers & Profiles”。

224803-86841ee28c20acbc.jpg

  • 選擇在 Certificates 欄下的“All”。

  • 點擊下圖中紅色邊框內的加號按鈕。

224803-099549fdfcccf7c0.jpg

  • 選擇 “Production” 欄下的 “Apple Push Notification service SSL (Sandbox & Production)” 勾選後,點擊下一步。

12_ios_apns_certificate_2_2x.jpg

  • 從 App ID 下拉菜單中選擇你需要的 App ID ,點擊下一步。

224803-a90a1e88f501ec6a.jpg

  • 這時會出現 About Creating a Certificate Signing Request (CSR)。

cer2.jpg

  • 根據它的說明創建 Certificate Signing Request。

224803-63e17b9d51906490.jpg

  • 點擊下圖中的 “Choose File” 按鈕:

12_ios_apns_certificate_3_2x.jpg

  • 上傳剛剛生成的 .certSigningRequest 文件 生成 APNs Push Certificate。

  • 下載證書。

  • 雙擊打開證書,證書打開時會啟動鑰匙串訪問工具。

  • 在鑰匙串訪問工具中,你的證書會顯示在 “證書” 中,注意選擇左下角的 “證書” 和左上角 “登錄”。

224803-38c9767bf0ea70af.jpg

結束語

對於 APNs 而言,iOS 9 的這一更新是有劃時代意義的,請即刻敦促你們公司的服務端進行升級,或者使用支持新 APNs 協議的 SDK 進行推送服務。 文中如有錯誤,並請幫忙指正,反饋請發往微博@iOS程序犭袁。

參考鏈接:

Configuring Push Notifications

APNs Provider API

HTTP/2 Protocol for iOS Push Notification Server(APNS)

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved