個推百億級訊息推送的優先順序解決方案
作者|個推資深研發專家 微風
引言
馬上就是春節了,面對井噴的推送需求、百億級推送下發壓力,服務了數十萬App的個推,是如何持續最佳化技術方案,保障高優先順序訊息實時下發的?本文將從業務場景、方案設計思路、方案闡述等方面講述個推百億級訊息推送的優先順序解決方案。
業務場景
在日常訊息推送過程中,個推往往需要應對來自以下四方面的挑戰。
• 高併發:單臺伺服器在每日高峰時段需要響應百萬級併發量請求
• 低延遲:需毫秒級響應推送請求,保障億級訊息秒級送達
• 海量資料:需在每日百億級推送下發請求中,實現訊息的實時下發
• 海量使用者:需要在個推業務層中對外標識的百億使用者裡快速篩選出符合推送條件的目標群體進行訊息下發
當同時有多個App進行訊息下發時,難免會出現資源競爭的情況, 因此就產生了優先順序佇列的需求:在下發資源固定的情況下, 高優先順序的使用者需要有更多的下發資源。
方案設計思路
為了應對上述四點挑戰,我們採用了以下三項原則予以指導:
• 保證相對公平、避免飢餓問題
• 避免互相干擾、阻塞
• 動態調整下發速度
業務方案
上文介紹了打包構建方案的流程,但是在實踐中,我們會發現隨著構建的任務越來越多,構建的環境會變得越來越繁雜,難以管理。
基於以上三點原則,結合具體業務場景,我們制定瞭如下兩套解決方案。
方案概述
• 個推採用基於Kafka 的優先順序佇列方案,解決了訊息下發場景中面臨的任務大小不一、下發量大、時延低三大難題。
• 個推採用基於Pulsar 的優先順序佇列方案,解決了訊息回執場景中面臨的回執響應時間不一、優先順序需實時調整這兩大難題。
1、基於Kafka 的優先順序佇列方案
一般情況下,早上7 - 9點、中午12 - 13點、 晚上19 - 21點這三個時間段,個推收到的推送任務比較集中,其訊息量佔全天的七八成。在這些推送任務中,我們都會針對手機型別、區域分佈、使用者群體特徵等複雜條件篩選出需要送達的使用者,而不同客戶的使用者量差距較大,範圍在幾百到上億之間。面對這些客戶同時傳送的推送請求時,個推需要保障推送訊息實時到達,避免客戶之間下發速度互相影響。
業務邏輯
針對實際遇到的挑戰與我們的方案規劃思路,最終設計的落地方案如圖所示:
當訊息推送處於低峰期、機器資源處於低水位執行時,訊息不進入佇列,直接傳送給App;
當訊息推送併發量變高、機器資源處於中水位執行時,訊息進入內部佇列排隊,待訊息被消費後再傳送給App;
當訊息推送併發量繼續增大、機器資源處於高水位執行時,訊息需要削峰填谷、降低資源競爭。它的具體實現方式是:
訊息進入外部佇列Kafka中排隊,內部佇列只接收從外部佇列出來的訊息,訊息從內部佇列被消費後傳送給App;
當外部佇列內的訊息消費完,機器資源執行水位緩慢降低到中水位時,內部佇列才開始接收其他渠道的推送訊息。這樣可以避免訊息之間的資源競爭,還可以保持後續處理邏輯的統一性。
下文我們將以資源進入高水位執行時的場景來舉例說明。
細節方案
由上圖可知,推送訊息會根據所屬的App ID區分高中低優先順序。在同優先順序的情況下,Kafka生產者首先會給大中小任務傳送不同的topic,由對應的Kafka消費者執行緒放入有界阻塞佇列中;接著按照 6:3:1的比例消費,比如一次取1000條推送訊息,高中低優先順序將分別獲得600、300、100的推送訊息量;
然後,排程執行緒將這批訊息下發給手機;如果此時高優先順序推送訊息處於低峰期,配額沒用完,假設只用了300,那麼剩下的300配額會按 3:1 的比例分配給中、低優先順序的消費者執行緒, 以此充分提高資源的利用率,且達到大中小任務不相互阻塞、不同優先順序任務不相互干擾的目的。
2、基於Pulsar 的優先順序佇列方案
當訊息下發後,大多數客戶都希望及時瞭解這條推送訊息是否已經到達App端,是否已經被系統展示以及是否被使用者及時點選檢視,故我們每天發給客戶的回執量也是巨大的。此業務場景主要涉及到的挑戰有:
由於每個客戶的網路情況、機器效能、業務處理邏輯等各不相同,因此個推發給客戶的回執響應時間也不同,快的十幾毫秒就可返回,慢的則需十幾秒甚至更久,且有些客戶的響應時間是在這個區間內不定期波動。
由於回執訊息數量巨大,所以Pulsar也需要先進入佇列排隊再傳送給客戶服務端。有些客戶為了提高回執傳送速度,會申請調整優先順序,我們服務端需要對此進行實時調整,提高回執速度。
結合挑戰和上述提及的方案設計思路,我們的落地方案如圖所示:
相比基於Kafka 的優先順序佇列方案,此方案的業務邏輯相對比較簡單,所有的回執訊息先進入外部佇列中,再透過排程執行緒統一把回執訊息傳送給客戶服務端。
由於我們需要實時調整優先順序,且希望回執響應速度不同的客戶之間不互相阻塞和影響,所以我們優先考慮了Pulsar元件。該元件的資料傳輸效能表現優秀且具備建立百萬級topic的能力。
個推利用此特性為每個App都建立了不同的topic,為我們後續實時調整優先順序和下發速度打下了強有力的基礎,詳情見細節方案。
細節方案
由上圖可知,回執訊息會被劃分到不同組,組內則會按優先順序程度傳送給客戶,具體步驟為:
首先,手機回執訊息到達個推服務端後,訊息會進入外部佇列Pulsar中排隊,接著不同的Pulsar消費者組會依據組內不同的優先順序,按照6:3:1的比例獲取一批迴執訊息,然後傳送至客戶的服務端。
App維度的回執訊息所屬的組是不固定的,每過一段時間,個推會根據不同的回執響應時間,透過K-means聚類演算法動態調整App所屬的組別,保證組內的傳送速度相近,使回執響應速度不同的客戶互不影響,且同組內高優先順序使用者能擁有較多的回執資源。
總結
以上是個推結合訊息下發和回執場景整理出的兩種解決方案。概括起來,重點為:
• 場景不同,方案不同
訊息下發 -- 高峰期內訊息下發量大、推送任務大小不一,訊息需要被快速下發,為此個推選擇了基於Kafka(內外部)優先順序佇列方案;
訊息回執 -- 需要動態聚合回執響應時間不一的訊息、動態調整優先順序,為此個推選擇了基於Pulsar(不同組別)優先順序佇列方案。
• 方案不同,MQ不同
內外部優先順序佇列方案 - - 需要滿足短時間內傳輸大量訊息資料,為此個推選擇了Kafka元件;
不同組別優先順序佇列方案 -- 需要為每個App都建立各自的topic,為此個推選擇了Pulsar元件。
建議開發者在選擇方案的時候,多結合業務場景進行思考,從而找到最為合適的落地方案。服務了數十萬App的個推,還會在“訊息推送”這個領域深入擴充,持續為開發者們分享前沿的理念與最新的實踐方案。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31556026/viewspace-2747583/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 個推基於 Apache Pulsar 的優先順序佇列方案Apache佇列
- RMQ——支援合併和優先順序的訊息佇列MQ佇列
- CSS優先順序CSS
- 運算子的優先順序
- python運算子及優先順序順序Python
- 等級+時間的優先順序演算法演算法
- Android程式優先順序Android
- 中斷優先順序
- Yacc使用優先順序
- [譯]HTTP/2的優先順序HTTP
- 快速掌握RabbitMQ(三)——訊息確認、持久化、優先順序的C#實現MQ持久化C#
- Python 列表推導及優先順序佇列的實現Python佇列
- SpringBoot配置檔案優先順序載入順序Spring Boot
- SQL 優先順序join>whereSQL
- java運算子優先順序Java
- 同一個元素中有多個class,優先順序
- 推導相等優先順序為何彈出棧頂
- 設計中的優先順序(下)
- SAP UI configuration determination的優先順序UI
- 設計中的優先順序(上)
- CSS 選擇器的優先順序CSS
- 測試用例的優先順序
- 解析 RocketMQ 業務訊息--“順序訊息”MQ
- 關於RocketMQ的順序訊息MQ
- css 選擇器優先順序CSS
- Yarn任務優先順序配置Yarn
- ansible 變數優先順序示例變數
- C++運算子優先順序C++
- java setPriority()設定優先順序Java
- 封裝優先順序佇列封裝佇列
- nginx的location匹配順序、優先順序,location對映衝突排查Nginx
- 優先順序點陣圖演算法詳解演算法
- Java之執行緒的優先順序Java執行緒
- 【分享】如何評估 bug 的優先順序
- 【pytest】fixture 與 setup, teardown 的優先順序
- 怎樣做好客戶的優先順序?
- html優先順序和層疊性HTML
- 任務卡片優先順序排序-Leangoo排序Go