網誌好讀版:http://hungys.logdown.com/posts/240029-azure-notification-hubs-overview
在上一篇文章中,我們與讀者介紹了 Azure Mobile Services 這個提供全面性 App 後端的服務,而其中它支援了多平台的推播通知,然而,某些情形之下,這樣的服務可能還無法滿足需求。設想今天您的用戶數已經突破數百萬甚至上千萬,當需要將某則訊息廣播至所有裝置時,若一次 reuqest 只傳送給一個終端裝置的話,代表得要花上數百數千萬的 reuqest 才能完成,想必會相當耗時。
這時熱血的開發者一定會跳出來說,那我們就來自幹一個推播系統吧!如果要應付這樣的需求,首先要解決的便是盡可能地在單次 request 中將訊息遞送給更多的終端用戶來達到減少總 reuqest 數的目標,關於這點每個平台會有不同的作法及策略:
然而,前面所提到的減少 request 次數只是最基本的一步,即便將 request 數量降低至數十萬,要在推送完還是得花上不少時間,所以必須設計好一個堅固的分散式系統來處理這些請求,然而,您可能並非隨時都在大量推送通知,於是便可能會產生運算性能的閒置。
最後一個問題則是錯誤處理,並不是每個通知都能夠成功的發送至裝置端,可能會因為任何因素而發送失敗,甚至是該裝置的 token 已經失效,這部分的處理也必須自己來。綜合以上,除非您的團隊有相當充足的開發人力來處理這些需求,否則使用現有的大量推播服務可能還是比較好的選擇。除了本文要介紹的 Notification Hubs 之外,您亦可以參考如Parse、Urban Airship 這類的服務,與這些服務相比,Notification Hubs 較注重的是建立一個彈性的基礎架構,所以它並不像其他服務有提供較為完整的後端 console 能夠操作。
Azure Notification Hubs 主要專注在群組廣播的推播服務上,讓您可以在數秒、數分鐘之內就把一則訊息推送至上百萬的終端裝置。此外,微軟支援了 GCM、APNS 以及自家的 WNS、MPNS 服務,讓您可以透過單一服務來處理各個平台的裝置,甚至在最近一次更新中增加了對百度推播系統的支援。
若您使用了 Notification Hubs,所有與 GCM、APNS、WNS... 等推播系統之間的溝通都可以交給 Azure 來處理,您所需要做的事情只是在 Client 端增加向 Notification Hubs 註冊的請求,並且之後要傳送推播皆透過 Notification Hubs 所提供的端點,剩餘的實作都由微軟官方所負責處理,當然甚至包含了推播過程中所產生的錯誤。
整體來說,Notification Hubs 具有以下幾點特色及功能:
在 Notification Hubs 中,每個終端裝置皆需要向 Azure 註冊,而註冊主要分為兩種實作方式,第一種是直接使用官方提供的 SDK 將註冊程序置入在您的 App 中,該 SDK 會直接透過 REST API 向 Notification Hubs 註冊該裝置如圖所示:
而另一種方法則是將註冊的程序寫在您自己的 Server 後端中,如此一來 App 中僅需透過您自己的 API 端點註冊即可,完全不需與 Notification Hubs 互動。而這種做法最大的好處在於裝置的 tag 是從 Server 端註冊的,所以您可以在使用者沒有打開 App 時來修改他的 tag:
每個註冊的裝置都可以擁有各自的**「Tag」**,而且可以包含兩個以上的 tag,舉個例來說,您可以為 A 球隊的支持者們註冊一個 teamA 的標籤,B 球隊的支持者們則註冊 teamB,屆時若要推送關於 A 球隊的最新比數,直接向 teamA 這個 tag 推送即可。這個 tag 可以是任意長度小於 120 的字串,您甚至可以為每個使用者 ID 皆註冊一個 tag,如此一來便可以達到針對單一使用者推播的需求,如下圖:
除了單一 tag 之外,您也可以使用**「Tag expression」**來表達所要推送的對象,它可以包含如「&&」、「||」、「!」的邏輯運算子,以下圖為例,您可以使用 (follows_RedSox || follows_Cardinals) && location_Boston 這個 expression 來表達「居住在波士頓,並且追蹤紅襪或紅雀」這群使用者:
標籤的使用可以相當彈性,以筆者的使用方法為例,舉凡 userid:<USER ID>、version:<VERSION>、installAt:<INSTALL DATE> ...等等的 tag 在發送推播時都相當實用,但免費及基本方案有限制最多只能有 3000 種 tag,所以使用方法上便要特別留意。
然而,這項功能也有所限制,如果您只使用了「||」這個 OR 運算子,則最多可以在單一 expression 中包含 20 個 tag,除了這個 case 之外,混用 AND、OR、NOT 的情況下最多只能包含 6 個不同的 tag,這點必須留意。
樣板這個功能主要能解決兩個目的,其中第一個是剛剛有提到過的使用單一 payload 格式來對應多種平台,以下圖為例,Windows Phone 裝置及 Android 裝置分別對樣板做了註冊,其中包含了「message」這個共同參數,未來您在推播時,僅需要給定該參數的值即可對有註冊該樣板的用戶推送:
另一種使用方式則是個人化或本地化的通知,以下圖的例子來說,某些裝置註冊了「華氏」的樣板,某些裝置則註冊了「攝氏」的樣板,屆時您只需要在 payload 中給定「tempF」及「tempC」參數的值,便可自動對應到這兩種樣板,您也可以使用在多國語系通知的實作上:
關於樣板語法的詳細說明可以參考:http://msdn.microsoft.com/en-us/library/azure/dn530748.aspx
在付費方案中,您可以設定排程通知,他會回傳一個 scheduled notification 的 ID,您必須自行儲存這組 ID,未來若要取消排程時會使用到,目前 Management Portal 上也沒有相關的介面能夠管理排程通知,您只能透過 REST API 來存取。
更多關於 API 的細節,請參考:http://msdn.microsoft.com/en-us/library/azure/dn495101.aspx
目前 Notification Hubs 幾乎支援所有主流平台,並且在官方網站上提供了相對應的文件可以參考:
其中,Windows Phone 比較特別的是本身具有 MPNS 及較新的 WNS 兩種推播平台,目前官方的 Notification Hubs SDK for Windows Phone Silverlight 僅支援 MPNS,所以若您的 App 是 Windows Phone Silverlight 8.1 的專案,而且想要使用較新的 WNS 服務,則不能直接使用官方提供的 SDK,必須透過 REST API 來操作。而筆者為了專案上的需求,所以寫了一個非官方的 SDK 來支援 WNS,但目前僅支援基本功能,並不包括「範本註冊」的支援,相關原始碼皆可在 GitHub 上「Azure Notification Hubs SDK for Silverlight 8.1 using WNS」的專案中找到,歡迎 fork 它並完善它!目前筆者有在實際的專案中使用這個 SDK,相信對於基本的推播需求是能夠正常來使用的!
Azure 官方在今年九月份(2014/9)修改了這個服務的收費機制,這點必須要特別注意,因為有用量上及功能上的差別。目前主要分為**「免費」、「基本」、「標準」**三種層級,它們的差異可摘要如下:
然而,與 Amazon 的 Simple Notification Service (SNS) 相比,SNS 本身是 topic/subscribe 的概念,但與 Notification Hubs 的 tag 機制正好相反,topic 必須是在 SNS 上事先建立好才能由裝置註冊,而且即便是付費方案仍有單一 topic 的裝置數上線。筆者曾經比較過這兩個服務,基本上 Notification Hubs 能夠符合較多的情境及需求!
本文簡單的介紹了 Notification Hubs 這項服務,筆者認為這是一個非常值得嘗試的服務,而且免費方案提供了滿充足的基本推播量。無奈比較可惜的是,最新的收費機制雖然對免費方案提供了更龐大的推播量,但相對的卻拔除了一些進階功能如排程推播、註冊查詢的功能,並且限制了單次廣播的裝置數上線,但低價方案與標準方案之間的價差甚大,希望官方未來能增加更多彈性的資費方案。