簡介: 轉(zhuǎn)自閑魚技術(shù) 作者:今朝 、有攸
OpenIMgithub開源地址:
https://github.com/OpenIMSDK/Open-IM-Server
OpenIM官網(wǎng) :https://www.rentsoft.cn
OpenIM官方論壇:https://forum.rentsoft.cn/
引言
閑魚消息系統(tǒng)經(jīng)過幾代開發(fā)的建設(shè),目前穩(wěn)定的支撐億級消息體量。在消息系統(tǒng)建設(shè)過程中,我們經(jīng)歷了從簡單到復(fù)雜,從困擾到破局,每一次的技術(shù)改變都是為了更好的解決當(dāng)下業(yè)務(wù)面臨的問題?!皯浳粑鐦驑蛏巷嫞卸嗍呛烙ⅰ?,此文記錄閑魚消息系統(tǒng)技術(shù)變遷,以期在此基礎(chǔ)上汲取更多經(jīng)驗。
閑魚消息1.0:業(yè)務(wù)初創(chuàng)期,最小化可用
背景:14年啟動閑置交易獨立APP “閑魚”,一期構(gòu)建完成APP主鏈路,包含商品發(fā)布→搜索→商品詳情→IM會話→交易。作為初創(chuàng)app,業(yè)務(wù)需盡快上線驗證效果,技術(shù)建設(shè)上需要完成閑魚消息從無到有的系統(tǒng)搭建。
作為即時通訊系統(tǒng),最小化能力包含
消息存儲:會話、摘要、消息
消息同步:推、拉
消息通道:長連接、廠商推送
與一般IM會話模型不同的是,閑魚會話以商品為主體,人+人+商品為要素構(gòu)建會話,因會話模型的差異,淘系已有的消息系統(tǒng),短期內(nèi)無法滿足業(yè)務(wù)需求,而閑魚完全自建消息系統(tǒng)耗時巨大。為了保障業(yè)務(wù)高效上線,技術(shù)選型上最大化復(fù)用已有系統(tǒng)能力,避免重復(fù)造輪子。所以,
數(shù)據(jù)模型與底層存儲依賴淘系私信體系進行建設(shè);
消息數(shù)據(jù)獲取上,客戶端全量從服務(wù)端拉取消息數(shù)據(jù)
通訊協(xié)議使用來往SDK及mtop
總體架構(gòu)如下圖,以此模式完成快速交付保障了業(yè)務(wù)最小化可用

閑魚消息2.0:用戶量高增速,重建閑魚消息系統(tǒng)
背景: 閑魚用戶量快速突破100W,消息服務(wù)調(diào)用量暴漲。常態(tài)性的,用戶反饋消息數(shù)據(jù)獲取卡頓、白屏,大量的push發(fā)送下,系統(tǒng)告警頻發(fā)。
造成這些問題的原因:消息1.0 模式下,獲取消息數(shù)據(jù)全量拉模式,客戶端純UI不做數(shù)據(jù)存儲
當(dāng)用戶需要查看消息數(shù)據(jù)時,數(shù)據(jù)拉取成功與否取決于網(wǎng)絡(luò)、數(shù)據(jù)訪問速度,偶發(fā)性的造成卡頓、白屏
中心化的數(shù)據(jù)存儲,讀遠(yuǎn)大于寫,高并發(fā)下,服務(wù)端負(fù)載過大比如1W個用戶同時在線聊天,按照當(dāng)前架構(gòu)并發(fā)拉取全量消息,估算5Wqps. 不妨假設(shè),同時在線聊天用戶數(shù)10W時,對服務(wù)端壓力可想而知
基于上述問題,我們決定重建消息系統(tǒng),以應(yīng)對未來更大的用戶增量?;貧w到IM系統(tǒng)的核心功能消息存儲模型:會話模型:由owner、itemid、user、sessionType 來標(biāo)識唯一會話,增加擴展屬性支持個性化摘要模型:作為用戶會話視圖,同一會話的不同用戶可個性化呈現(xiàn),由userid、sid標(biāo)識唯一摘要消息模型:由sender、消息內(nèi)容、消息版本、sid組成。sid+消息版本唯一確定一條消息指令模型:是一種雙端約定,由服務(wù)端下發(fā),客戶端執(zhí)行的指令集。如免打擾指令、刪除指令等消息通道:在線通道:使用淘寶無線ACCS長連接提供的全雙工、低延時、高安全的通道服務(wù)。離線通道:使用淘寶消息推送平臺AGOO. 其屏蔽了各主流廠商對接的復(fù)雜度,直接對業(yè)務(wù)系統(tǒng)提供服務(wù)消息同步模型:1.客戶端建立數(shù)據(jù)庫,存儲消息數(shù)據(jù)

? ? 當(dāng)消息數(shù)據(jù)存儲在本地設(shè)備上,消息同步從全量拉取優(yōu)化為全量+增量同步結(jié)合的模式。 增量同步:客戶端存儲消息位點信息,通過與服務(wù)端最新位點比較,僅同步增量消息;全量同步:當(dāng)用戶卸載重裝或位點gap過大時,客戶端全量拉取歷史消息數(shù)據(jù),進行端上數(shù)據(jù)重建
2.服務(wù)端建設(shè)個人消息域環(huán)(收件箱模型),以和客戶端進行增量數(shù)據(jù)同步。同時,消息1.0版本存在的讀多寫少的問題,通過個人域環(huán)的寫擴散來平衡讀寫壓力
下圖為一條消息從發(fā)送到接收的過程以及服務(wù)端和客戶端的執(zhí)行流程

如圖所示,假設(shè)Ua給Ub發(fā)送一條消息,消息寫擴散至Ua和Ub的各自的域環(huán)中。1.當(dāng)客戶端online時,接收到推送的消息位點=當(dāng)前端上域版本+1,本地消息數(shù)據(jù)庫merge即可2.當(dāng)客戶端offline時,僅進行離線推送通知,當(dāng)用戶重新上線時,進行數(shù)據(jù)同步,由服務(wù)端判斷觸發(fā)增量同步還是全量同步
如果域環(huán)版本差值小于閥值,增量同步后,進行本地消息數(shù)據(jù)庫merge
當(dāng)域環(huán)版本差值大于閥值,進行全量消息拉取,做端上數(shù)據(jù)重建
整個同步邏輯基于閑魚的消息域環(huán),域環(huán)可以看作是有著固定容量的用戶消息收件箱,給一個用戶發(fā)送的所有消息都會同步到他的域環(huán)中。域環(huán)存儲:域環(huán)需要支持高并發(fā)數(shù)據(jù)讀寫,使用阿里分布式KV存儲系統(tǒng)tair來實現(xiàn)域環(huán)容量:為減少全量消息同步,以用戶下次進入閑魚需要同步的平均消息量來規(guī)劃個人域環(huán)容量。同時利用FIFO循環(huán)覆蓋歷史數(shù)據(jù)域環(huán)版本:用戶當(dāng)前消息位點,在消息進入個人域環(huán)時通過tair的counter實現(xiàn)域環(huán)版本嚴(yán)格連續(xù)遞增,用于全量、增量同步判斷
上述建設(shè)完成后,閑魚具備了自己獨立的消息系統(tǒng),當(dāng)下遇到的問題得到了緩解,用戶體驗度有大幅提升。
閑魚消息3.0:業(yè)務(wù)快速發(fā)展下,系統(tǒng)穩(wěn)定性保障
背景: 隨著閑魚業(yè)務(wù)生態(tài)的豐富,IM會話與消息內(nèi)容類型不斷擴展,同時在DAU的快速增長下,用戶反饋消息收不到、消息延遲等輿情問題日漸突出。

問題分析:1.閑魚app進程無有效保活機制,app退到后臺后進程很快就會被系統(tǒng)掛起,導(dǎo)致長連接中斷。此時消息推送走廠商通道,而廠商通道的實時性較差,且對消息推送的優(yōu)先級設(shè)定有差異,從而造成用戶感知消息延遲2.accs在線消息推送時,平均延時較短,但存在假連情況,而且目前的消息推送鏈路無ack機制,造成服務(wù)端以為消息發(fā)出去了但實際上客戶端并沒有收到,用戶下次打開app后才能看到消息,用戶感知消息延遲。造成假連接的原因:用戶退到后臺,accs長連中斷,但是設(shè)備狀態(tài)更新有延時。3.目前消息同步的推模式(accs push)、拉模式(mtop),客戶端未做隔離,異步進行處理,導(dǎo)致在某些極端情況下消息數(shù)據(jù)庫處理異常,引發(fā)消息丟失。比如某用戶上線后連續(xù)收到多條消息,其中一條觸發(fā)域黑洞,在進行消息同步端上數(shù)據(jù)重建時,小概率處理出錯。4.大部分線上消息問題發(fā)現(xiàn)靠輿情反饋,如消息錯亂,出問題后系統(tǒng)無感知、無補救措施且排查困難,僅能跟隨版本做修復(fù)5.業(yè)務(wù)不斷豐富,孵化出基于消息系統(tǒng)的服務(wù)號及小程序內(nèi)容營銷、消息群組等,各類消息發(fā)送鏈路共用域環(huán)與數(shù)據(jù)存儲,造成穩(wěn)定性問題。如個人域環(huán)的消息包括IM聊天和營銷消息,IM聊天由用戶觸發(fā),需要保證強到達(dá);而營銷消息一般是由系統(tǒng)通過班車等方式批量發(fā)送,消息量級大,tps高,影響IM服務(wù)穩(wěn)定性
基于上述分析,我們進行專項解決:消息重發(fā)與推拉隔離ACK: 保障消息及時到達(dá)。服務(wù)端下行accs消息時,將消息加入重試隊列并延遲重試,客戶端在收到accs消息并處理成功后,給服務(wù)端回一個ack,服務(wù)端收到ack后更新消息到達(dá)狀態(tài),并終止重試,以此避免設(shè)備假連或網(wǎng)絡(luò)不穩(wěn)定的情況。重發(fā):根據(jù)延遲重發(fā)策略決定何時重發(fā)消息,保障消息確定性到達(dá)。自適應(yīng)延遲重發(fā)策略是指新消息先通過4次固定N秒的短延遲來探測設(shè)備的網(wǎng)絡(luò)狀況,然后根據(jù)網(wǎng)絡(luò)狀況來遞增固定步長M的延遲策略,這種策略可以保障在最短的時間內(nèi),使用最少的重發(fā)次數(shù)將消息投遞成功。消息隊列:端上引入消息隊列,按順序處理消息,保證消息處理的準(zhǔn)確性。同時進行推拉隔離,保障隊列有序消費,解決了復(fù)雜狀況下并發(fā)處理消息數(shù)據(jù)合并出錯的問題。

數(shù)據(jù)存儲拆分閑魚每天發(fā)送的消息中有一半以上是營銷消息,營銷消息的發(fā)送具有明顯的波峰波谷流量,高峰期會導(dǎo)致消息數(shù)據(jù)庫抖動,影響IM消息。對消息、摘要、域環(huán)存儲做業(yè)務(wù)隔離,以適應(yīng)不同業(yè)務(wù)場景對穩(wěn)定性不同的要求。
IM消息需要極高的穩(wěn)定性保證,其消息及摘要繼續(xù)使用mysql存儲
營銷消息存儲周期短,穩(wěn)定性要求低于IM,采用Lindorm存儲。Lindorm是一種多模型的云原生數(shù)據(jù)庫服務(wù),具有成本低、自定義TTL、容量橫向擴展等優(yōu)勢
域環(huán)做實例級別隔離,保證IM域環(huán)的容量不會被其他消息占用,從而影響到消息同步

線上問題發(fā)現(xiàn)與恢復(fù)保障穩(wěn)定性的關(guān)鍵要素是做好各種核心指標(biāo)的監(jiān)控,而監(jiān)控首先要有數(shù)據(jù)來源,對服務(wù)端+客戶端的關(guān)鍵鏈路節(jié)點埋點,基于集團UT、SLS,通過blink進行實時清洗、計算,最終形成統(tǒng)一規(guī)范的日志數(shù)據(jù)落至SLS,以供實時監(jiān)控及鏈路排查。消息系統(tǒng)的核心目標(biāo)是保障用戶消息發(fā)的出、收得到且及時收到,所以我們通過計算發(fā)送成功率、到達(dá)率、消息延遲來監(jiān)控系統(tǒng)的穩(wěn)定性。此外,為了解決用戶輿情排查困難的問題
我們設(shè)計了一套指令集,通過約定指令協(xié)議,服務(wù)端向指定用戶下發(fā)指令,客戶端執(zhí)行對應(yīng)指令進行異常數(shù)據(jù)上報,提高排查效率
擴展了強制全量同步、數(shù)據(jù)校正等指令,定向修復(fù)用戶消息數(shù)據(jù)問題,相較以往出現(xiàn)嚴(yán)重bug只能讓用戶卸載重裝解決,這種方式顯然對用戶是更友好的

經(jīng)過一系列專項治理,技術(shù)類輿情下降50%,從0到1建設(shè)了消息穩(wěn)定性體系,用戶體驗進一步提升。
最后:龐大的用戶體量下,追求極致的NPS
閑魚作為電商交易APP, 其中IM是交易的前置鏈路,IM的產(chǎn)品體驗極大影響用戶交易效率前段時間進行用戶調(diào)研,從閑魚IM NPS低于預(yù)期(NPS是用戶忠誠度衡量指標(biāo) = 推薦者%-貶損者%),從用戶反饋來看:
部分用戶對產(chǎn)品功能有較強烈的訴求,諸如消息搜索、分組等
大部分用戶對發(fā)送消息過程中的違規(guī)問題難以理解
仍有較多輿情反饋消息收不到或延遲
映射到目前閑魚的消息系統(tǒng)上,我們的系統(tǒng)架構(gòu)依然有很多需要持續(xù)改進的地方。典型的如同步協(xié)議冗余,在需求迭代過程中容易引發(fā)問題、有效保活機制的缺失對消息即時送達(dá)的影響、小眾機型離線消息收不到、多年的數(shù)據(jù)積累在線庫臃腫等問題,影響著閑魚業(yè)務(wù)迭代速度與NPS。將提升NPS作為核心目標(biāo),閑魚消息4.0進行時....
OpenIM官網(wǎng) :https://www.rentsoft.cn
OpenIM官方論壇:https://forum.rentsoft.cn/
更多原創(chuàng)技術(shù)文章:
開源OpenIM:高性能、可伸縮、易擴展的即時通訊架構(gòu)
https://forum.rentsoft.cn/thread/3
【OpenIM原創(chuàng)】簡單輕松入門 一文講解WebRTC實現(xiàn)1對1音視頻通信原理
https://forum.rentsoft.cn/thread/4
【OpenIM原創(chuàng)】開源OpenIM:輕量、高效、實時、可靠、低成本的消息模型
https://forum.rentsoft.cn/thread/1
OpenIM服務(wù)發(fā)現(xiàn)和負(fù)載均衡golang插件:gRPC接入etcdv3
https://forum.rentsoft.cn/thread/2
【OpenIM原創(chuàng)】簡單輕松入門 一文講解WebRTC實現(xiàn)1對1音視頻通信原理
https://forum.rentsoft.cn/thread/4
【OpenIM原創(chuàng)】C/C++調(diào)用golang函數(shù),golang回調(diào)C/C++函數(shù)