從0到1,億級(jí)消息推送的穩(wěn)定性保障
1、消息推送簡(jiǎn)介
1.1 什么是消息推送
消息推送每天都在我們的手機(jī)上發(fā)生,如圖所示,除非你的手機(jī)沒(méi)有安裝App或關(guān)閉了通知欄權(quán)限。
1.2 消息推送的價(jià)值
從用戶的生命周期來(lái)看,消息推送對(duì)于提高App活躍度、提升用戶粘性和用戶留存率都起到了重要作用。
- 提升新用戶次日留存,低成本促活,對(duì)平臺(tái)的短期留存率影響顯著。
- 提升老用戶活躍度,push可以通過(guò)外部提醒起到拉活的作用。很多內(nèi)容平臺(tái)類App的用戶push首次啟動(dòng)占比可達(dá) 10%以上,因此push對(duì)DAU的增量貢獻(xiàn)不容小覷。
- 流失用戶召回,當(dāng)用戶流失后,若push權(quán)限未關(guān)閉,通過(guò)消息推送的方式,有可能重新喚醒用戶。
2、背景和痛點(diǎn)
消息中心為得物App提供了強(qiáng)大,高效的用戶觸達(dá)渠道,其中push對(duì)于得物DAU的貢獻(xiàn)有可觀的占比,這也就意味著每一條推送消息都是一次與用戶溝通的寶貴機(jī)會(huì),所以推送的穩(wěn)定性成為我們關(guān)注的首要問(wèn)題,那么我們遇到的以下痛點(diǎn)就亟待解決。
- 消息中心沒(méi)有明確消息推送的耗時(shí)標(biāo)準(zhǔn),業(yè)務(wù)和技術(shù)之間存在gap,業(yè)務(wù)方對(duì)于推送的消息什么時(shí)候到達(dá)沒(méi)有明確的心理預(yù)期。
- 從技術(shù)上來(lái)講消息推送各個(gè)節(jié)點(diǎn)的耗時(shí)不明確,無(wú)法對(duì)各個(gè)節(jié)點(diǎn)的耗時(shí)做針對(duì)性的優(yōu)化,這也就需要我們針對(duì)消息推送的節(jié)點(diǎn)耗時(shí)進(jìn)行監(jiān)控。
- 消息推送的穩(wěn)定性依賴于第三方的推送通道,而三方通道對(duì)于我們來(lái)講就是個(gè)黑盒子,如何做到三方通道異常及時(shí)發(fā)現(xiàn)并止損也是需要考慮的問(wèn)題。
- 在我們正常的迭代過(guò)程中有時(shí)候不可避免的會(huì)出現(xiàn)些異?;蛘哂袎奈兜赖拇a,這些問(wèn)題能不能及時(shí)發(fā)現(xiàn)、及時(shí)止損,能不能及時(shí)告警出來(lái)。
3、監(jiān)控的實(shí)踐
3.1 SLA監(jiān)控簡(jiǎn)介
SLA(Service-Level Agreement),也就是服務(wù)等級(jí)協(xié)議,指的是系統(tǒng)服務(wù)提供者(Provider)對(duì)客戶(Customer)的一個(gè)服務(wù)承諾。這是衡量一個(gè)大型分布式系統(tǒng)是否“健康”的常見(jiàn)方法。在開(kāi)發(fā)設(shè)計(jì)系統(tǒng)服務(wù)的時(shí)候,無(wú)論面對(duì)的客戶是公司外部的個(gè)人、商業(yè)用戶,還是公司內(nèi)的不同業(yè)務(wù)部門(mén),我們都應(yīng)該對(duì)自己所設(shè)計(jì)的系統(tǒng)服務(wù)有一個(gè)定義好的SLA。因?yàn)镾LA是一種服務(wù)承諾,所以指標(biāo)可以多種多樣。最常見(jiàn)的四個(gè)SLA指標(biāo),可用性、準(zhǔn)確性、系統(tǒng)容量和延遲。
對(duì)于消息推送而言,我們主要關(guān)注的是消息能否及時(shí)可靠的送達(dá)給用戶,也就是SLA中關(guān)注的時(shí)效性和穩(wěn)定性的問(wèn)題。目前消息中心針對(duì)實(shí)效性和穩(wěn)定性的開(kāi)發(fā)已經(jīng)完成并初顯成效,下面主要針對(duì)時(shí)效性和穩(wěn)定性的監(jiān)控做一些介紹。
3.2 系統(tǒng)架構(gòu)圖
3.3 時(shí)效性監(jiān)控
3.3.1 節(jié)點(diǎn)的拆分
如何做到時(shí)效性的無(wú)死角監(jiān)控,那么我們就要對(duì)消息推送的整個(gè)流程進(jìn)行拆分,把整個(gè)流程拆分成若干個(gè)獨(dú)立且無(wú)依賴的可監(jiān)控節(jié)點(diǎn)。從消息系統(tǒng)流轉(zhuǎn)圖中可以看到,整個(gè)推送流程是清晰明了的,消息的的推送主要會(huì)經(jīng)歷推送鑒權(quán)、用戶查詢、防疲勞過(guò)濾、防重復(fù)過(guò)濾等的邏輯處理,考慮到每個(gè)業(yè)務(wù)邏輯的處理是相互獨(dú)立且無(wú)依賴的,那我們就可以根據(jù)具體的業(yè)務(wù)處理邏輯進(jìn)行節(jié)點(diǎn)的拆分,這樣就可以做到拆分無(wú)遺漏,監(jiān)控?zé)o死角,拆分后的具體節(jié)點(diǎn)如下:
3.3.2 節(jié)點(diǎn)耗時(shí)的計(jì)算
具體的節(jié)點(diǎn)拆分邏輯和耗時(shí)邏輯的計(jì)算如下圖:
備注:
節(jié)點(diǎn)耗時(shí)的計(jì)算:記錄節(jié)點(diǎn)消息推送到達(dá)的時(shí)間,并計(jì)算節(jié)點(diǎn)推送耗時(shí),例如防疲勞耗時(shí)=T7(antiFatigueConsumeTime)-T6(checkrepeatConsumeTime)
節(jié)點(diǎn)阻塞量的計(jì)算:記錄節(jié)點(diǎn)消息推送的瞬時(shí)阻塞量, 例如防疲勞節(jié)點(diǎn)阻塞量 = 防疲勞的總量-防疲勞已經(jīng)處理的量
3.3.3 節(jié)點(diǎn)指標(biāo)的制定
既然需要監(jiān)控的節(jié)點(diǎn)已經(jīng)拆分明確了,那針對(duì)這些節(jié)點(diǎn)我們監(jiān)控哪些指標(biāo)才是有意義的呢。
- 目前消息推送高峰耗時(shí)較長(zhǎng),各業(yè)務(wù)域?qū)τ谙⒌牡竭_(dá)時(shí)間也沒(méi)有明確的心理一個(gè)預(yù)期,另外消息中心也無(wú)法感知推送在整個(gè)鏈路各個(gè)節(jié)點(diǎn)的耗時(shí)情況,無(wú)法針對(duì)節(jié)點(diǎn)耗時(shí)做到有針對(duì)性的優(yōu)化,所以節(jié)點(diǎn)的推送量和推送耗時(shí)就是我們需要重點(diǎn)關(guān)注的指標(biāo)。
- 節(jié)點(diǎn)的阻塞量可以讓我們及時(shí)感知到推送中存在的積壓?jiǎn)栴},在大促期間,消息的推送量也會(huì)達(dá)到一個(gè)高峰,消息目前是否有堆積,處理的速度是否跟的上,是否需要臨時(shí)擴(kuò)容,那么節(jié)點(diǎn)的阻塞量就成了一個(gè)比較有意義的參考指標(biāo)。
考慮到消息推送是有優(yōu)先級(jí)的并且區(qū)分單推和批量推,所以我們要針對(duì)不同的優(yōu)先級(jí)和推送方式設(shè)置不同的標(biāo)準(zhǔn),消息推送耗時(shí)的具體標(biāo)準(zhǔn)如下。
3.3.4 技術(shù)方案的實(shí)現(xiàn)
為了能感知到消息推送中發(fā)生的異常和耗時(shí)情況,這就需要我們標(biāo)準(zhǔn)化監(jiān)控指標(biāo)和監(jiān)控的節(jié)點(diǎn)。其中耗時(shí)指標(biāo)可以感知節(jié)點(diǎn)的耗時(shí)和代碼的壞味道,阻塞量可以監(jiān)控到節(jié)點(diǎn)的堆積情況,推送成功率可以感知節(jié)點(diǎn)的推送異常等。另外節(jié)點(diǎn)拆分后我們可以很快定位到異常發(fā)生的具體位置,經(jīng)過(guò)拆分監(jiān)控的主要節(jié)點(diǎn)包括鑒權(quán)、風(fēng)控、用戶查詢、防疲勞、防重復(fù)、廠商調(diào)用等。
另外消息中心每天推送大量消息給得物用戶,SLA監(jiān)控任何一個(gè)操作嵌入主流程中都可能導(dǎo)致消息推送的延遲。這也就要求監(jiān)控和主流程進(jìn)行隔離,主流程的歸主流程,SLA 的歸 SLA,SLA 監(jiān)控代碼從主流程邏輯中剝離出來(lái),徹底避免SLA代碼對(duì)主流程代碼的污染,這也就要求SLA邏輯計(jì)算需要獨(dú)立于推送業(yè)務(wù)的主流程進(jìn)行異步計(jì)算,防止SLA監(jiān)控拖垮整個(gè)主流程,那么Spring AOP+Spring Event就是最好的實(shí)現(xiàn)方式 。
3.3.5 結(jié)果
消息推送實(shí)效性監(jiān)控做完之后,對(duì)服務(wù)節(jié)點(diǎn)耗時(shí)異??梢约皶r(shí)感知,同時(shí)也完成了關(guān)鍵節(jié)點(diǎn)耗時(shí)的指標(biāo)化,可以明確的看到所有節(jié)點(diǎn)在各個(gè)時(shí)間的耗時(shí)情況,同時(shí)也對(duì)消息推送針對(duì)各個(gè)節(jié)點(diǎn)的的優(yōu)化起到了指導(dǎo)作用。
時(shí)效性節(jié)點(diǎn)監(jiān)控:
時(shí)效性節(jié)點(diǎn)告警:
3.4 廠商推送監(jiān)控
3.4.1 監(jiān)控指標(biāo)制定
消息推送接入的有多個(gè)推送通道,如何做到對(duì)這些通道做到無(wú)死角的監(jiān)控,及時(shí)感知呢。
- 在做廠商監(jiān)控之前,我們就已經(jīng)遇到了廠商通道推送跌零的情況,這種情況下整個(gè)推送通道都掛掉了,我們要及時(shí)通知廠商進(jìn)行修復(fù),所以廠商推送跌零告警和廠商余量監(jiān)控是必須的。
- 從現(xiàn)有數(shù)據(jù)來(lái)看,廠商的推送成功率、回執(zhí)成功率、點(diǎn)擊率都穩(wěn)定在一定的的區(qū)間。如果廠商推送的指標(biāo)數(shù)據(jù)偏離這個(gè)區(qū)間則說(shuō)明推送有異常,所以推送成功率、回執(zhí)成功率、點(diǎn)擊率的監(jiān)控是必須的。
- 另外從業(yè)務(wù)請(qǐng)求發(fā)送的用戶數(shù)來(lái)看,每天的消息推送基本是穩(wěn)定的,相對(duì)應(yīng)的廠商的回執(zhí)數(shù)量和點(diǎn)擊數(shù)量也是穩(wěn)定的,那么對(duì)廠商推送成功的數(shù)量,回執(zhí)的數(shù)量和點(diǎn)擊的數(shù)量監(jiān)控也有一定的參考意義。
業(yè)務(wù)側(cè)請(qǐng)求發(fā)送的用戶數(shù):
廠商監(jiān)控告警:
3.4.2 技術(shù)方案實(shí)現(xiàn)
廠商每天有數(shù)億的消息推送,這也就意味著廠商的監(jiān)控不能嵌在主流程中處理。廠商的監(jiān)控代碼要從主流程邏輯中剝離出來(lái),避免監(jiān)控拖垮主流程,同樣避免監(jiān)控異常影響到推送的主流程。針對(duì)廠商推送的監(jiān)控,目前使用的是有界內(nèi)存隊(duì)列實(shí)現(xiàn)。
3.4.3 結(jié)果
消息推送廠商監(jiān)控上線之后,可以及時(shí)感知到廠商推送的異常信息,對(duì)于廠商推送的異常和廠商規(guī)則的更改等可以做到及時(shí)的感知。
4、帶來(lái)的收益
4.1 異常的及時(shí)發(fā)現(xiàn)
監(jiān)控上線后及時(shí)發(fā)現(xiàn)了發(fā)現(xiàn)了廠商推送線程關(guān)閉失敗,廠商推送跌零、廠商營(yíng)銷消息規(guī)則更改、廠商通道偶發(fā)不可用等問(wèn)題,并做到了及時(shí)的止損。
- 在時(shí)效性監(jiān)控上線之后,發(fā)現(xiàn)了因廠商推送線程創(chuàng)建關(guān)閉失敗導(dǎo)致線程數(shù)逐漸上升問(wèn)題,避免了線上故障的發(fā)生。
- 廠商異常導(dǎo)致推送跌零,監(jiān)控發(fā)現(xiàn)后及時(shí)通知到廠商并止損。
- 發(fā)現(xiàn)廠商營(yíng)銷消息規(guī)則更改的異常,并及時(shí)經(jīng)梳理各大廠商文檔后發(fā)現(xiàn)除了多個(gè)廠商通道在未來(lái)一個(gè)月內(nèi)也會(huì)有規(guī)則的更改,消息平臺(tái)及時(shí)適應(yīng)了廠商規(guī)則,接入廠商系統(tǒng)通道,做到了及時(shí)止損。
4.2 服務(wù)性能的提升
時(shí)效性監(jiān)控上線后發(fā)現(xiàn)了多個(gè)服務(wù)可以優(yōu)化的點(diǎn),其中多個(gè)廠商和推送節(jié)點(diǎn)在高峰推送時(shí)耗時(shí)較高,很明顯節(jié)點(diǎn)耗時(shí)和廠商推送 SDK 連接池和連接時(shí)間參數(shù)需要優(yōu)化。優(yōu)化后消息推送整體的吞吐量實(shí)現(xiàn)了翻倍的提升。
5、展望未來(lái)
由于時(shí)間問(wèn)題,目前消息監(jiān)控只做了時(shí)效性和廠商推送穩(wěn)定性相關(guān)的監(jiān)控,但是監(jiān)控上線后帶來(lái)的收益還是比較可觀的,可以預(yù)見(jiàn)的是監(jiān)控的構(gòu)建在未來(lái)必將帶給我們更大的收益,后續(xù)我們可以從以下點(diǎn)豐富現(xiàn)有監(jiān)控。
- 考慮到業(yè)務(wù)預(yù)的推送量和推送時(shí)間是穩(wěn)定的,那么我們可以針對(duì)業(yè)務(wù)維度添加推送數(shù)據(jù)的監(jiān)控,及時(shí)感知上游推送數(shù)據(jù)的變化。
- 其次我們可以針對(duì)各個(gè)節(jié)點(diǎn)的推送異常、漏斗轉(zhuǎn)化率、服務(wù)性能等做監(jiān)控,進(jìn)一步豐富消息平臺(tái)的監(jiān)控體系。
- 對(duì)于消息推送來(lái)講也要考慮推送的轉(zhuǎn)化率問(wèn)題,那么卸載、屏蔽等指標(biāo)也是我們需要監(jiān)控的點(diǎn),通過(guò)這些業(yè)務(wù)指標(biāo)及時(shí)感知推送的效果,做到精細(xì)化的管控。
6、總結(jié)
消息平臺(tái)監(jiān)控上線后帶來(lái)的收益還是比較可觀的,包括多次異常的及時(shí)發(fā)現(xiàn)和止損,還有發(fā)現(xiàn)多個(gè)個(gè)可以優(yōu)化的性能點(diǎn),實(shí)現(xiàn)了服務(wù)高峰吞吐量的翻倍,同時(shí)也解決了我們現(xiàn)在遇到的以下痛點(diǎn)。
- 時(shí)效性明確的給到了不同優(yōu)先級(jí)的耗時(shí)標(biāo)準(zhǔn),避免了業(yè)務(wù)和技術(shù)之間的gap,業(yè)務(wù)方對(duì)于推送的耗時(shí)也有了明確的心理預(yù)期。
- 時(shí)效性使得節(jié)點(diǎn)耗時(shí)的性能問(wèn)題可以一目了然,通過(guò)對(duì)現(xiàn)有節(jié)點(diǎn)耗時(shí)問(wèn)題的優(yōu)化,消息服務(wù)的吞吐量實(shí)現(xiàn)了翻倍的提升。
- 廠商穩(wěn)定性監(jiān)控使得廠商異??梢约皶r(shí)感知,其中廠商穩(wěn)定性監(jiān)控上線后發(fā)現(xiàn)多起廠商推送的異常,并做到了及時(shí)的解決和止損。
- SLA時(shí)效性和廠商穩(wěn)定性上線后,消息中心可以及時(shí)感覺(jué)到推送鏈路的異常和代碼的壞味道,特別是對(duì)于新上線的代碼,如果存在異??梢约皶r(shí)感知。