每個app或者業務都有將資訊推送到使用者客戶端的需求。作為中颱的推送平臺,需要為公司內部許多個不同app同時提供可用,穩定的推送服務,因此我們訊息推送平臺應運而生。
推送平臺架構
名詞解釋:
dt:全稱deviceToken,代表裝置唯一標識。
appId:使用者在推送平臺申請的應用代號。
token:平臺上每個應用對應的專屬金鑰。
msgId:每次推送呼叫,平臺生成的訊息唯一標識。
平臺側服務:
send-pservice:對外提供推送平臺網站,使用者可以在網站上進行申請應用,建立推送,檢視資料等操作。
send-api:對外提供介面服務,包括JSF和http兩種方式,介面包含推送,解綁,登出等。
send-worker:主要負責拉取定時推送,進行傳送。
通道側服務:
habitat:負責裝置資料庫的相關操作,包括繫結,解綁,上報,登出等。
mutate:負責接收推送請求,處理推送的pin,dt對應關係,及推送通道的適配。
report:上報服務,負責接收裝置首次登入時,生成的dt上報。
channel:負責傳送最後的推送請求到各個推送通道。
slark:回執服務,負責接收部分廠商通道推送後的非同步回執資訊,並做後續處理。
其他:
自建通道:由平臺搭建的推送通道服務,負責維護長連線,推送訊息到客戶端。
廠商通道:由外部廠商提供的系統級推送服務。
DataAnalysis:平臺的資料統計服務,負責統計推送的流轉資料。
業務方進行推送有兩種方式,一個是通過推送平臺網站在頁面上建立推送,第二個是通過呼叫我們提供的api服務的方式,進行推送。推送型別分為廣播和指定使用者推送,使用者可用在建立推送的時候指定型別,指定人群或者裝置。
平臺內部收到訊息推送的請求後,請求內如果是以裝置形式推送,系統會直接將推送內容和dt組合,推送給推送通道。如果請求是以人群pin方式推送,系統通過pin找到對應的所有有效裝置,然後以內容加dt的方式進行推送。推送通道分為兩種,自建通道和廠商通道。廠商通道是手機或者系統的廠商提供的系統級別推送通道,由手機系統維護,相對穩定。自建通道是我們自研的推送通道服務,通過自建通道服務與客戶端之間維持的長連結,對線上裝置進行推送。
關鍵資料準備
在應用維度,訊息推送平臺是為不同的app提供推送服務,所以需要為每個app生成appId以及對應的token,用於業務方呼叫推送平臺認證使用。
在裝置維度,平臺會儲存dt,pin和appId的對應關係,用於具體推送訊息的組建以及裝置資料的維護。
在訊息維度,平臺對於每次業務方推送請求的呼叫,生成一個msgId,並返回給呼叫方,這個msgId會在整個推送過程中被攜帶,從推送平臺生成,推送到自建或者廠商通道,觸達到客戶端,最後回執給推送平臺。這種方式是對整個推送流程追蹤的必備條件,方便排查問題和推送資料統計。
關鍵技術環節
1
推送請求的處理
業務方推送可以通過平臺頁面建立,和呼叫send-api服務介面兩種方式,後者的使用較為頻繁。平臺提供http和JSF兩種介面呼叫形式,推送請求按照實時性分類,可以分為即時推送訊息和定時推送訊息。
對於要求即時推送的訊息請求,api服務在接到有效呼叫後,會立即呼叫通道側的推送介面進行推送。對於需要定時推送的訊息,api服務會將任務寫到redis的有序集合中。send-worker會定時拉取各個應用集合中的推送任務,並將到達推送時間的任務取出,進行封裝,呼叫通道側服務進行推送,得到成功回執後,將任務移除。
為了提高介面效能,除基礎引數校驗之外,其他請求處理流程均採用非同步方式。使用執行緒池執行每次推送請求的處理過程,縮短響應時間。這樣可以減小高併發大量請求時,因響應時間過長,導致的響應超時或者JSF執行緒池耗盡的情況發生。
2
請求廠商通道
通道側在收到平臺側封裝好的推送請求後,會篩選出dt,然後將訊息內容體和dt組合在一起,去請求廠商通道。如果業務方傳的是pin,系統則會根據對應關係定位到pin對應的dt集合。當有廠商回執清理dt,或者業務方呼叫解綁或者登出dt介面時,這個dt集合是動態實時更新的。對於一次推送到大量dt的相同訊息體,也就是群推或者廣播的情況,系統會將dt分組傳送,以控制請求體的大小。
在高併發請求的情況下,請求廠商通道很可能出現廠商限流導致失敗的情況。當請求失敗出現後,系統都會去進行重試,但是這個時候的重試如果時間間隔太短,其重試是無意義的,廠商通道在這麼短的時間內可能還是限流狀態,重試間隔如果太長,又會降低請求的效率,還消耗系統的記憶體。
因此推送平臺對於這種情況採用了可配置的重試策略,實現對重試的次數和重試時間間隔的動態調整配置,方便根據廠商通道的具體情況對重試機制進行熱更新。
3
長連線的建立與維護
自建通道是訊息推送平臺自己搭建的長連線推送通道服務,目的是為無法接入廠商通道的裝置提供有效的推送途徑。
長連線的建立:
自建通道的長連線是基於TCP+TLS實現的。當客戶端上線動作觸發時,會向服務端機器傳送請求,服務端接收到請求之後,會返回給客戶端一個心跳引數,這個引數會作為雙方無資料互動時的心跳間隔。此後,客戶端在正常情況下,如果與服務端沒有資料互動,也會定時傳送心跳至服務端,雙方長連線建立成功。
我們會根據實際的網路及伺服器情況,動態適配heartbeatConfig引數,包括斷開時間間隔Idle和心跳傳送間隔heartbeat,都可以進行動態調整。
長連線的維護:
客戶端的第一次請求觸發onConnect動作後,服務端會把客戶端ctx與自建通道叢集的連線關係維護起來。當雙方在Idle時間內既無資料互動,又無心跳連結時,服務端會判定該客戶端下線,對應長連線已斷開,客戶端的所有連線記錄會被自動解除。
在長連線過程中,可能出現網路斷開導致客戶端斷連重連現象。即在Idle時間內,同一個客戶端向服務端請求第二次建連,這時可能出現一個客戶端與服務端建立兩個長連線的情況。對於這種問題,服務端採用斷開老連線,接受新連線的形式,保證叢集中每臺裝置長連線的唯一性。
使用長連線進行推送:
當通道側的channel服務受到最終的推送請求後,會將訊息體和dt最終封裝成請求通道的形式。對於使用自建通道的裝置,channel會自動識別到該裝置對應的伺服器單機ip,將推送請求傳送到對應機器進行推送。識別不到則判定裝置不線上,無法進行推送。
自建長連線的安全保障:
對於自建通道的長連線服務來說,安全性是十分重要的。我們主要從兩方面對安全性做了保障。第一個是自建通道使用TLS加密的服務端域名。第二個是使用自定義的編解碼方式,在服務端和客戶端SDK之間,我們統一使用事先規定好的自定義編碼和解碼方式,來提高資料層面的安全性。
4
推送回執的處理
每個廠商通道包括自建通道的回執引數標準都不統一,平臺的slark服務用於接收推送通道的回執訊息,目前接入回執服務的廠商包括華為,魅族,小米和OPPO。針對不同的通道,平臺會根據每個通道的回執引數標準,為每個通道做單獨的回執資訊處理,例如根據返回碼進行無效dt的清理,客戶端開啟推送後的流水傳送(用於資料統計)等。
平臺數據統計
1
訊息維度資料
推送資料對於一個推送平臺來說必不可少,這些資料既可以用於每個業務方檢視自己每條推送的狀態效果,方便他們更好的制定推送策略,同時也讓每條推送有跡可循,方便了推送整個流程的問題排查。
推送狀態包括處理,傳送,觸達,開啟。訊息處理和傳送兩個狀態由通道側處理節點生產到kafka,訊息的觸達和開啟由SDK上報給廠商或者自建通道,再由通道回執給slark服務,生產到kafka。
推送平臺對於訊息推送提供了多維度的資料統計,包括對每臺裝置,每個使用者的推送記錄,還有群推和廣播各個環節的總體數量統計,並體現觸達率和開啟率。
同時,還提供了推送通道維度的推送狀況統計,以及近期推送走勢圖,可以讓業務方從多個角度,清晰準確的觀察到自己每條推送的結果。
2
裝置維度資料
裝置資料方面,平臺除了儲存每條dt的詳細對應關係外,還對於每個應用的裝置總量,每日的新增裝置,清理裝置,關閉裝置進行了單獨統計和展示。同時也提供了手機品牌(安卓),型號(IOS)維度的裝置資料統計。
3
資料統計的實現
技術實現方面,資料的統計使用了flink計算程式,通過全流程攜帶的msgId,訊息型別,推送狀態以及客戶端上報的裝置型別等欄位,計算出各個維度的推送資料。在每臺裝置這個維度的推送資料方面,使用了elasticSearch,對推送資料的必要欄位進行了落地,支援使用者以pin的形式,查詢對應所有裝置的推送情況。
監控與報警
對於一個成熟的平臺化產品,對於自身業務及服務的監控和報警必不可少。訊息推送平臺在內部系統,使用者使用需求兩個方面都設定了詳細的監控埋點,制定了可靠的報警規則。
在內部系統方面,推送平臺針對每個新建的應用都添加了appId對應的介面埋點監控,當介面的呼叫量,效能,可用率發生變化時,平臺管理員會根據報警,找到對應的應用負責人,方便及時的了解情況,定位問題,解決問題。同時也對關鍵叢集中的機器設定了記憶體,CPU報警規則,及時監控服務端叢集效能。
此外平臺還對於每個應用所上傳的證書進行每日定時檢查。由一個定時任務程式每天拉取所有應用證書,解析證書有效期,平臺會對已經失效,或者還剩7天失效的證書應用負責人進行郵件,簡訊等形式的報警,以敦促使用者儘快更換證書,避免問題出現。