轉: 58同城高性能移動Push推送平臺架構演進之路

轉: http://geek.csdn.net/news/detail/58738css

 

文/孫玄程序員

本文詳細講述58同城高性能移動Push推送平臺架構演進的三個階段,並介紹了什麼是移動Push推送,爲何須要,原理和方案對比;移動Push推送第一階段(單平臺)架構如何設計;移動Push推送典型性能問題分析解決,以及高可用、高性能、高穩定性如何保證。安全

什麼是移動Push推送

移動Push推送是移動互聯網最基礎的需求之一,用於知足移動互聯環境下消息到達App客戶端。以轉轉(58趕集旗下真實我的的閒置交易平臺)爲例,當買家下單後,咱們經過移動Push推送消息告訴賣家,當賣家已經發貨時,咱們經過移動Push消息告訴買家,讓買賣雙方及時掌握二手商品交易的實時訂單動態。bash

爲何須要移動Push推送?

移動互聯網絡環境下,常常會出現弱網環境,特別是2G、3G等網絡環境下,網絡不夠穩定,App客戶端和相應服務器端的長鏈接已經斷開,消息沒法觸達App客戶端。而咱們業務須要把Message(轉轉App交易消息等)、Operation(轉轉App運營活動等)、Alert(轉轉紅包未消費提醒等)等消息推送給App客戶端,從而觸發用戶看到這些消息,經過點擊這些Push消息達到相應目標。服務器

推送原理和方案對比

移動Push推送主要有如下三種實現方式。網絡

  1. 移動App輪詢方式(PULL) 
    App客戶端按期發起Push消息查詢請求,來達到消息推送的目的。PULL方案的優勢和缺點都比較明顯,總體架構簡單但實時性較差,咱們能夠經過加快查詢頻率,提升實時性,但這會形成電量、流量消耗太高。
  2. 移動App基於短信推送方式(SMS Push) 
    經過短信發送推送消息,並在客戶端置入短信攔截模塊,能攔截短信,並解析後轉發給App應用處理。這個方案實時性好、到達率高,但成本很高。
  3. 移動App長鏈接方式(Push) 
    移動Push推送基於TCP長鏈接實現,消息實時性好,這是目前主流的實現方式,須要維護App客戶端和服務端的長鏈接心跳,會帶來額外的電量、流量消耗;在架構設計時,須要作些折中,以免流量和電量的大量消耗。此外Push推送技術架構複雜度較高,維護移動App客戶端的海量長鏈接請求,並創建與App客戶端通訊的加密通道,整合成內部少許有限的長鏈接,對通訊數據進行壓縮與解壓,以節省流量。

目前移動Push推送技術基本都是結合這3個方案進行,但對於不一樣的移動終端平臺,又有各自不一樣的實現,這裏詳細介紹iOS和Android平臺上的具體實現方案。多線程

iOS平臺架構

對於iOS平臺,因爲其特殊性,移動Push推送相對簡單,iOS應用是不容許service後臺常駐的,因此你沒有別的選擇,也沒辦法經過開發本身的Push service來完成推送下發,只能經過蘋果APNS方式來完成。iOS移動Push推送流程如圖1所示。併發

圖片描述

圖1 iOS移動PUSH推送流程

 

Android平臺異步

在Android平臺上,因爲對service常駐沒有限制,可用的方案就多一些:能夠經過Google官方C2DM 完成、開源方案(例如XMPP)、藉助第三方,或者徹底自主研發的移動Push推送方案。 
Google C2DM的主要流程如圖2所示。

圖片描述

圖2 C2DM移動PUSH推送流程

 

Google C2DM和Apple APNS流程大體相似,但其最大的問題是移動Push推送服務器在國外,很容易被屏蔽,並且Push推送延遲較大。此外因爲 Android社區分裂比較嚴重,不少廠商直接就把C2DM模塊給去掉了,因此在國內這個方案極不可靠,變成了一個理論上的方案。

移動Push推送開源方案

對於開源移動Push推送協議,常見的有XMPP等, 事實上Google的C2DM底層也是基於XMPP協議實現的,咱們經過線下測試發現,開源移動Push推送方案主要有兩個問題:第一,沒有ACK機制,消息到達沒有保證,不可靠;第二,當移動Push消息請求量併發增大時,系統開始變得不穩定,甚至出現了模塊宕機的狀況。所以直接使用移動Push推送開源方案,也不是很是可靠,我我的建議:在大規模使用開源的移動Push推送方案以前,必須作到對開源技術方案總體把握住,否則一旦出現問題,沒法及時定位和修復的話,帶來的後果將會是災難性的。

藉助第三方移動Push推送方案

除此以外,目前移動Push推送市場上,還有很多第三方推送產品可供選擇,但須要面臨如下幾個問題:

  • 到達率 
    雖然第三方移動Push推送產品都宣傳到達率高於90%,可是實際使用起來,發現遠遠達不到。固然到達率低的問題,除了第三方移動Push推送平臺自己技術緣由外,還和業務推送方的用戶選取有很大關係,若是用戶較活躍,到達率就會高些,若是用戶不活躍,或者用戶已經卸載了相應的App客戶端,必然形成到達率進一步下降。

  • 實時性&控制度 
    第三方移動Push推送產品的推送通道是共用的,會面向多個推送客戶,若是某一個客戶Push推送量特別大,那麼其餘的消息實時性可能就會受到影響,這些都是業務推送方不可控的,會比較被動。

徹底自主研發的移動Push推送方案

咱們曾經考慮實現一套徹底自主的移動Push推送平臺,若是從零開始來作,須要解決幾個難點:第一,移動Push推送服務端對移動App客戶端海量長鏈接的維護管理。第二,App客戶端常駐 service穩定性,如何使Push service常駐?咱們能夠藉助父子進程互相監控的方式來作到,一旦發現對方進程不在了,會從新創建,繼續循環監控。第三,手機內存不足時,系統會殺掉Push service,甚至有些操做系統比較強勢,它會向iOS系統同樣並不容許第三方Push service 常駐。第四,移動Push推送到達率的提升,除了技術手段外,還有一些PR的手段,好比移動App客戶端Push service經過在相應操做系統上添加白名單的方式使其永久常駐。總之,在移動互聯複雜的場景下如何讓移動Push推送到達率變得更高,不是一件簡單的事兒。

58同城移動Push推送方案

咱們綜合考慮前面講述的開源、基於第三方、徹底自主研發方案,58同城並無選擇從零開始徹底自主研發而是採用了基於第三方移動Push推送平臺和自主研發高性能Provider的方案(如圖3所示),知足天天百億量級的吞吐量,並經過動態組合和擴展的方式,結合離線的移動Push推送數據分析,不一樣手機使用不一樣的推送策略,針對性地優化。在Android平臺,咱們融合多種第三方移動Push平臺,從而有效提高到達率。

圖片描述

圖3 58同城移動PUSH推送平臺技術架構

 

第一階段(單平臺):架構如何設計

背景&需求

2011年咱們研發了58幫幫,這是一款知足58用戶和商戶之間溝通的即時通信軟件,用戶間能夠互相添加好友、收發消息等。58幫幫的消息推送基於App客戶端和服務器的長鏈接,一旦這條長鏈接斷開,那麼IM服務端的消息將沒法推送給App客戶端,用戶也沒法看到這些消息。在iOS平臺上,58幫幫App切換到後臺後,App與IM的長鏈接斷開,消息沒法觸達,這時候咱們須要藉助iOS APNS機制,IM消息須要發送給APNS,APNS再轉發對應的消息到58幫幫App。Android切換至後臺,App與IM的長鏈接保持,IM消息能夠正常推送,所以在這個階段咱們須要解決的問題是在iOS平臺上,當58幫幫App切後臺後,IM在長鏈接斷開後的消息觸達需求。

設計目標

基於上述的背景和需求,咱們在設計移動Push推送第一階段(單平臺)架構時,首先要知足在iOS平臺上,當IM長鏈接斷開後,IM消息的可以觸達到App客戶端。其次咱們的移動Push推送協議設計也具有很好的擴展性,在能夠預見的將來,Push推送平臺將逐步接入更多的App,所以咱們設計目標iOSProvider是一個通用的iOS推送服務。不一樣App經過使用不一樣的移動Push推送證書藉助同一iOSProvider完成移動Push消息推送,對於不一樣App的接入,咱們採用了配置文件方式動態擴展接入,iOSProvider根據所配置App證書與APNS創建並維護多條TSL鏈接。配置文件的格式以下:

第一個域#第二個域#第三個域#第四個域

其中,第一個域爲推送服務類型Type,以備擴展,1爲APNS;第二個域爲內部定義的APPID號,對應服務的App;第三個域爲App的Apple證書文件名;第四個域爲與APNS創建的鏈接數; 
每一個App接入的配置爲一行,舉例以下:

1 #88 #zhuanzhuan.p12 #64 1 #66 #58tongcheng.p12 #32

除此以外,iOSProvider須要對每一個接入App的APNS鏈接池進行管理,動態增刪TSL鏈接,具有動態重連機制,並具備單獨的反饋接收線程,用於異步接收APNS返回無效的Token,反饋給移動Push推送業務方,用於下次移動Push消息推送的優化。iOSProdiver根據Type、APPID選擇對應的APNS鏈接,經過推送線程組裝APNS包發送到APNS服務器,如圖4所示。

圖片描述

圖4 iOSProvider架構圖

 

第二階段(多平臺):架構如何設計優化

隨着移動互聯時代的到來,58同城研發了多個App,每個App都有移動Push消息推送的需求(消息、運營活動、過時提醒等),而且每一款App同時具備多個終端:Android版、iOS版等。在這樣的需求背景下,咱們的移動Push推送平臺須要繼續演進,如何演進呢?

iOS移動Push推送通道能夠很好的知足業務推送需求,但目前還不具有Android移動Push推送的能力,所以咱們急須要研發Android移動Push推送通道。如何作?綜合目前可選擇的方案,咱們選擇了基於第三方推送平臺以及自主研發高性能AndroidProvider的方案。

首先重點講述針對Android移動Push推送的流程:第一,App客戶端向第三方移動Push推送平臺註冊,獲取對應的App惟一標示(Token)。第二,App將Token信息發送給AndroidProvider並集中存儲,以便後續基於Token的移動Push推送。第三,AndroidProvider經過HTTPS或者TSL的方式和第三方移動Push推送平臺創建鏈接,並把須要推送的消息發送到第三方移動Push推送平臺。第四,第三方移動Push推送平臺收到AndroidProver推送的消息後,會把此消息及時推送到App,從而完成整個推送過程,如圖5所示。

圖片描述

圖5 Android移動PUSH推送流程

 

AndroidProvider子系統總體結構分爲四個層次,第一層爲業務方移動Push推送接入,用於衆多移動Push推送業務方的接入。第二層爲網絡交互層,用於接收移動Push推送業務方的消息數據以及發送請求處理層的處理數據給業務推進調用。第三層爲請求處理層,用於處理網絡交互層放入請求隊列的數據,組裝成第三方移動Push推送接口須要的數據,經過HTTP或者HTTPS的方式調用下游的接口,並等待請求結果的返回,把請求返回的結果放入迴應隊列。第四層爲第三方移動Push推送平臺,由第三方提供,開放給使用方接口,供調用其功能,如圖6所示。

圖片描述

圖6 AndroidProiver系統架構圖

 

隨着愈來愈多的移動App接入,移動Push推送需求趨向多樣化,同時移動Push推送業務邏輯複雜化(多終端、批量發送、業務規則多樣),公共策略每一個業務方重複開發(深夜防打擾功能、發送頻率和發送速率的限制等),形成開發效率低下。爲了解決這些問題,咱們抽象了公共的邏輯,並進行了統一的封裝,對業務調用方透明,這些公共的邏輯包括:通用的策略和通用的控制,如圖7所示。

圖片描述

圖7 Android移動PUSH推送演進業務架構

 

在移動Push推送第二階段(多平臺)階段,咱們具有了Android、iOS的通道服務能力,知足推送消息的需求。可是咱們沒有提供統一的發送接口,業務方須要各自組包(Android、iOS)發送不一樣的推送通道,除此以外,推送通道性能方面還有待提高,推送通道穩定性還有待提高,此外推送通道包含了相對共同的業務邏輯,推送通道還不夠「純粹」。

第三階段:架構和協議如何設計和優化

移動Push推送第二階段還存在一系列的問題,所以在第三階段須要解決,而且隨着更多App接入,咱們須要提供公司級統一的高性能移動Push推送平臺。基於第三方移動Push推送平臺,咱們自主研發了知足天天推送百億量級的高性能Provider,推送平臺具有了高穩定性、接入方便,並提供了較高的推送到達率。

移動Push推送平臺第三階段咱們如何架構和設計?首先咱們知足對下游接入方多種鏈接的管理(HTTP、HTTPS、TCP、SSL、TSL),具有了多種鏈接動態伸縮性,從而知足Provider層對移動Push推送鏈接的要求。其次平臺要具有高併發的特性,經過徹底異步的設計和多線程支持,作到了高併發和支持10萬QPS吞吐量。再次咱們須要對接入下游的錯誤進行處理,一旦發現鏈接被斷開等錯誤後,要可以自動使用新的鏈接,而且對已經發出還沒到達App客戶端的推送消息進行重發,以保證消息不丟失。第四咱們須要對通道進行封裝,對外提供統一的友好接入接口,屏蔽底層iOS和Android接入的差別性。最後在Android移動推送方面,咱們接入了更多的第三方推送平臺,以達到更高的到達率。

基於這些方面的考慮,58同城移動Push推送平臺採用了低耦合的分層架構設計(如圖3所示),分爲三層Push Entry、Push Transfer、Provider(iOSProvider和AndroidProvider)。其中Push Entry是業務方調用的入口,咱們採用異步消息隊列的方式,提供了較高的業務方發送的速度,而且具有了消息緩衝的功能,使得高峯期的海量移動Push消息推送對整個平臺衝擊較少,也起到了保護推送系統的做用。Push Transfer會從Push Entry層接收消息進行解析,對推送消息進行合法性檢查,若是格式不合法,直接丟棄,同時會進行接收到的推送消息格式轉換成內部的消息格式,分平臺轉發到iOSProvider或者AndroidProvider上;provider接收到Push Transfer的消息後,會按照下游須要的消息格式(APNS協議、Android協議)進行轉換,進行消息的下發,在下發的過程當中,會進行消息的重發,以確保消息下發到第三方推送平臺。

Provider模塊內部如何設計?以iOSProvider爲例,它分爲三個層次:接入邏輯、業務邏輯、APNS出口。其中接入邏輯主要處理網絡交互和請求分發;業務邏輯主要處理線程分裂擴展、併發處理和錯誤處理;APNS出口處理向APNS的發送邏輯,如圖8所示。

圖片描述

圖8 iOSProvider模塊結構圖

 

對於移動Push推送平臺來講,追求達到率是咱們最核心的指標,沒有之一。所以在Android方面,咱們融合了多個第三方推送平臺,經過機型控制,對不一樣的機型使用不一樣通道,進一步提高推送到達率。AndroidProvider層進行消息推送策略的控制,先推送一通道,根據此推送通道ACK狀況,是否繼續推送其餘通道。推送多個Push通道,會出現推送消息重複到達App客戶端的情形,此時須要App客戶端根據推送消息ID進行去重,收到的重複推送消息忽略處理。

典型性能問題分析解決以及高可用、高性能、高穩定性如何保證

在移動Push推送不斷演進的過程當中,咱們遇到了AndroidProvider併發低的問題,仔細分析,是由於咱們採用HTTPS庫,因爲庫中HTTPS的鏈接實現不是線程安全的,對每一個HTTPS的請求都加鎖串行化處理,以保證線程的安全性。發現問題後,咱們經過在線上增長多進程部署的方式暫時解決,使得咱們有足夠的時間分析此問題產生的根本緣由。通過深刻分析,發現緣由是咱們對HTTPS的庫掌握不夠,致使加鎖粒度過大,經過HTTPS庫提供的更小粒度的鎖,咱們不只解決了線程不安全的問題,也提高了AndroidProvider的併發度,如圖9所示。

圖片描述

圖9 HTTPS庫細粒度鎖實現方式

 

總之,58同城統一的高性能移動Push推送平臺經過無狀態化設計和冗餘部署等方式確保了推送平臺的高可用,經過純異步、動態多線程的支持提供推送平臺的高性能,經過質量保證、多種監控機制(進程監控、語義監控、錯誤日誌監控、數據波動監控等),有問題及時發現處理保證了推送平臺的高穩定性。

最後,我要感謝項目組的同窗,特別感謝姚勁同窗,有了大家持續不斷的努力和付出,纔有了今天這篇文章;也感謝老婆大人,有你在背後默默的支持,纔有了今天這篇文章。


孫玄:58趕集集團系統架構師,技術負責人,技術委員會架構組主任,也是58同城即時通信、C2C技術負責人,負責58核心系統的架構以及優化工做。分佈式系統存儲專家,前百度高級工程師,參與社區搜索部多個基礎系統的設計與實現。

本文爲《程序員》原創文章,未經容許不得轉載,訂閱2016年《程序員》請點擊 http://dingyue.programmer.com.cn

相關文章
相關標籤/搜索