Jack Jiang

          我的最新工程MobileIMSDK:http://git.oschina.net/jackjiang/MobileIMSDK
          posts - 506, comments - 13, trackbacks - 0, articles - 1

          本文由阿里閑魚(yú)技術(shù)團(tuán)隊(duì)逸昂分享,原題“消息鏈路優(yōu)化之弱感知鏈路優(yōu)化”,有修訂和改動(dòng),感謝作者的分享。

          1、引言

          閑魚(yú)的IM消息系統(tǒng)作為買(mǎi)家與賣(mài)家的溝通工具,增進(jìn)理解、促進(jìn)信任,對(duì)閑魚(yú)的商品成交有重要的價(jià)值,是提升用戶(hù)體驗(yàn)最關(guān)鍵的環(huán)節(jié)。

          然而,隨著業(yè)務(wù)體量的快速增長(zhǎng),當(dāng)前這套消息系統(tǒng)正面臨著諸多急待解決的問(wèn)題。

          以下幾個(gè)問(wèn)題典型最為典型:

          • 1)在線(xiàn)消息的體驗(yàn)提升;
          • 2)離線(xiàn)推送的到達(dá)率;
          • 3)消息玩法與消息底層系統(tǒng)的耦合過(guò)強(qiáng)。

          經(jīng)過(guò)評(píng)估,我們認(rèn)為現(xiàn)階段離線(xiàn)推送的到達(dá)率問(wèn)題最為關(guān)鍵,對(duì)用戶(hù)體驗(yàn)影響較大。

          本文將要分享的是閑魚(yú)IM消息在解決離線(xiàn)推送的到達(dá)率方面的技術(shù)實(shí)踐,內(nèi)容包括問(wèn)題分析和技術(shù)優(yōu)化思路等,希望能帶給你啟發(fā)。

          學(xué)習(xí)交流:

          - 即時(shí)通訊/推送技術(shù)開(kāi)發(fā)交流5群:215477170 [推薦]

          - 移動(dòng)端IM開(kāi)發(fā)入門(mén)文章:《新手入門(mén)一篇就夠:從零開(kāi)發(fā)移動(dòng)端IM

          - 開(kāi)源IM框架源碼:https://github.com/JackJiang2011/MobileIMSDK 

          本文已同步發(fā)布于:http://www.52im.net/thread-3748-1-1.html )

          2、系列文章

          本文是系列文章的第6篇,總目錄如下:

          3、通信鏈路類(lèi)型的劃分

          從數(shù)據(jù)通信鏈接的技術(shù)角度,我們根據(jù)閑魚(yú)客戶(hù)端是否在線(xiàn),將整體消息鏈路大致分為強(qiáng)感知鏈路和弱感知鏈路。

          強(qiáng)感知鏈路由以下子系統(tǒng)或模塊:

          • 1)發(fā)送方客戶(hù)端;
          • 2)idleapi-message(閑魚(yú)的消息網(wǎng)關(guān));
          • 3)heracles(閑魚(yú)的消息底層服務(wù));
          • 4)accs(阿里自研的長(zhǎng)連接通道);
          • 5)接收方客戶(hù)端組成。

          整條鏈路的核心指標(biāo)在于端到端延遲和消息到達(dá)率。

          強(qiáng)感知鏈路中的雙方都是在線(xiàn)的,消息到達(dá)客戶(hù)端就可以保證接收方感知到。強(qiáng)感知鏈路的主要痛點(diǎn)在消息的端到端延遲。

          弱感知鏈路與強(qiáng)感知鏈路的主要不同在于:弱感知鏈路的接收方是離線(xiàn)的,需要依賴(lài)離線(xiàn)推送這樣的方式送達(dá)。

          因此弱感知鏈路的用戶(hù)感知度不強(qiáng),其核心指標(biāo)在于消息的到達(dá)率,而非延遲。

          所以當(dāng)前階段,優(yōu)化弱感知鏈路的重點(diǎn)也就是提升離線(xiàn)消息的到達(dá)率。換句話(huà)說(shuō),提升離線(xiàn)消息到達(dá)率問(wèn)題,也就是優(yōu)化弱感知鏈路本身。

          4、消息系統(tǒng)架構(gòu)概覽

          下圖一張整個(gè)IM消息系統(tǒng)的架構(gòu)圖,感受下整體鏈路:

          如上圖所示,各主要組件和子系統(tǒng)分工如下:

          • 1)HSF是一個(gè)遠(yuǎn)程服務(wù)框架,是dubbo的內(nèi)部版本;
          • 2)tair是阿里自研的分布式緩存框架,支持 memcached、Redis、LevelDB 等不同存儲(chǔ)引擎;
          • 3)agoo是阿里的離線(xiàn)推送中臺(tái),負(fù)責(zé)整合不同廠商的離線(xiàn)推送通道,向集團(tuán)用戶(hù)提供一個(gè)統(tǒng)一的離線(xiàn)推送服務(wù);
          • 4)accs是阿里自研的長(zhǎng)連接通道,為客戶(hù)端、服務(wù)端的實(shí)時(shí)雙向交互提供便利;
          • 5)lindorm是阿里自研的NoSQL產(chǎn)品,與HBase有異曲同工之妙;
          • 6)域環(huán)是閑魚(yú)消息優(yōu)化性能的核心結(jié)構(gòu),用來(lái)存儲(chǔ)用戶(hù)最新的若干條消息。

          強(qiáng)感知鏈路和弱感知鏈路在通道選擇上是不同的:

          • 1)強(qiáng)感知鏈路使用accs這個(gè)在線(xiàn)通道;
          • 2)弱感知鏈路使用agoo這個(gè)離線(xiàn)通道。

          5、弱感知鏈路到底怎么定義

          通俗了說(shuō),弱感知鏈路指的就是離線(xiàn)消息推送系統(tǒng)。

          相比較于在線(xiàn)消息和端內(nèi)推送(也就是上面說(shuō)的強(qiáng)感知鏈路),離線(xiàn)推送難以確保被用戶(hù)感知到。

          典型的情況包括:

          • 1)未發(fā)送到用戶(hù)設(shè)備:即推送未送達(dá)用戶(hù)設(shè)備,這種情況可以從通道的返回分析;
          • 2)發(fā)送到用戶(hù)設(shè)備但沒(méi)有展示到系統(tǒng)通知欄:閑魚(yú)曾遇到通道返回成功,但是用戶(hù)未看到推送的案例;
          • 3)展示到通知欄,并被系統(tǒng)折疊:不同安卓廠商對(duì)推送的折疊策略不同,被折疊后,需用戶(hù)主動(dòng)展開(kāi)才能看到內(nèi)容,觸達(dá)效果明顯變差;
          • 4)展示到通知欄,并被用戶(hù)忽略:離線(xiàn)推送的點(diǎn)擊率相比于在線(xiàn)推送更低。

          針對(duì)“1)未發(fā)送到用戶(hù)設(shè)備”,原因有:

          • 1)離線(xiàn)通道的token失效;
          • 2)參數(shù)錯(cuò)誤;
          • 3)用戶(hù)關(guān)閉應(yīng)用通知;
          • 4)用戶(hù)已卸載等。

          針對(duì)“3)展示到通知欄,并被系統(tǒng)折疊”,原因有:

          • 1)通知的點(diǎn)擊率;
          • 2)應(yīng)用在廠商處的權(quán)重;
          • 3)推送的數(shù)量等。

          針對(duì)“4)展示到通知欄,并被用戶(hù)忽略”,原因有:

          • 1)用戶(hù)不愿意查看推送;
          • 2)用戶(hù)看到了推送,但是對(duì)內(nèi)容不感興趣;
          • 3)用戶(hù)在忙別的事,無(wú)暇處理。

          總之:以上這些離線(xiàn)消息推送場(chǎng)景,對(duì)于用戶(hù)來(lái)說(shuō)感知度不高,我們也便稱(chēng)之為弱感知鏈路。

          6、弱感知鏈路的邏輯構(gòu)成

          我們的弱感知鏈路分為3部分,即:

          • 1)系統(tǒng);
          • 2)通道;
          • 3)用戶(hù)。

          共包含了Hermes、agoo、廠商、設(shè)備、用戶(hù)、承接頁(yè)這幾個(gè)環(huán)節(jié)。具體如下圖所示。

          從推送的產(chǎn)生到用戶(hù)最終進(jìn)入APP,共分為如下幾個(gè)步驟:

          • 步驟1:Hermes是閑魚(yú)的用戶(hù)觸達(dá)系統(tǒng),負(fù)責(zé)人群管理、內(nèi)容管理、時(shí)機(jī)把控,是整個(gè)弱感知鏈路的起點(diǎn)。;
          • 步驟2:agoo是阿里內(nèi)部承接離線(xiàn)推送的中臺(tái),是閑魚(yú)離線(xiàn)推送能力的基礎(chǔ);
          • 步驟3:agoo實(shí)現(xiàn)離線(xiàn)推送依靠的是廠商的推送通道(如:蘋(píng)果的apns通道、Google的fcm通道、及國(guó)內(nèi)各廠商的自建通道。;
          • 步驟4:通過(guò)廠商的通道,推送最終出現(xiàn)在用戶(hù)的設(shè)備上,這是用戶(hù)能感知到推送的前提條件;
          • 步驟5:如果用戶(hù)剛巧看到這條推送,推送的內(nèi)容也很有趣,在用戶(hù)的主動(dòng)點(diǎn)擊下會(huì)喚起APP,打開(kāi)承接頁(yè),進(jìn)而給用戶(hù)展示個(gè)性化的商品。

          經(jīng)過(guò)以上5個(gè)步驟,至此弱感知鏈路就完成了使命。

          7、弱感知鏈路面臨的具體問(wèn)題

          弱感知鏈路的核心問(wèn)題在于:

          • 1)推送的消息是否投遞給了用戶(hù);
          • 2)已投遞到的消息用戶(hù)是否有感知。

          這對(duì)應(yīng)推送的兩個(gè)階段:

          • 1)推送消息是否已到達(dá)設(shè)備;
          • 2)用戶(hù)是否查看推送并點(diǎn)擊。

          其中:到達(dá)設(shè)備這個(gè)階段是最基礎(chǔ)的,也是本次優(yōu)化的核心。

          我們可以將每一步的消息處理量依次平鋪,展開(kāi)為一張漏斗圖,從而直觀的查看鏈路的瓶頸。

          漏斗圖斜率最大的地方是優(yōu)化的重點(diǎn),差異小的地方不需要優(yōu)化:

          通過(guò)分析以上漏斗圖,弱感知鏈路的優(yōu)化重點(diǎn)在三個(gè)方面:

          • 1)agoo受理率:是指我們發(fā)送推送請(qǐng)到的數(shù)量到可以通過(guò)agoo(阿里承接離線(xiàn)推送的中臺(tái))轉(zhuǎn)發(fā)到廠商通道的數(shù)量之間的漏斗;
          • 2)廠商受理率:是指agoo中臺(tái)受理的量到廠商返回成功的量之間的漏斗;
          • 3)Push點(diǎn)擊率:也就通過(guò)以上通道最終已送到到用戶(hù)終端的消息,是否最終轉(zhuǎn)化為用戶(hù)的主動(dòng)“點(diǎn)擊”。

          有了優(yōu)化方向,我們來(lái)看看優(yōu)化手段吧。

          8、我們的技術(shù)優(yōu)化手段

          跟隨推送的視角,順著鏈路看一下我們是如何進(jìn)行優(yōu)化的。

          8.1 agoo受理率優(yōu)化

          用戶(hù)的推送,從 Hermes 站點(diǎn)搭乘“班車(chē)”,駛向下一站: agoo。

          這是推送經(jīng)歷的第一站。到站一看,傻眼了,只有不到一半的推送到站下車(chē)了。這是咋回事嘞?

          這就要先說(shuō)說(shuō) agoo 了,調(diào)用 agoo 有兩種方式:

          • 1)指定設(shè)備和客戶(hù)端,agoo直接將推送投遞到相應(yīng)的設(shè)備;
          • 2)指定用戶(hù)和客戶(hù)端,agoo根據(jù)內(nèi)部的轉(zhuǎn)換表,找到用戶(hù)對(duì)應(yīng)的設(shè)備,再進(jìn)行投遞。

          我們的系統(tǒng)不保存用戶(hù)的設(shè)備信息。因此,是按照用戶(hù)來(lái)調(diào)用agoo的。

          同時(shí):由于沒(méi)有用戶(hù)的設(shè)備信息,并不知道用戶(hù)是 iOS 客戶(hù)端還是 Android 客戶(hù)端。工程側(cè)不得不向 iOS 和 Android 都發(fā)送一遍推送。雖然保證了到達(dá),但是,一半的調(diào)用都是無(wú)效的。

          為了解這個(gè)問(wèn)題:我們使用了agoo的設(shè)備信息。將用戶(hù)轉(zhuǎn)換設(shè)備這一階段提前到了調(diào)用 agoo 之前,先明確用戶(hù)對(duì)應(yīng)的設(shè)備,再指定設(shè)備調(diào)用 agoo,從而避免無(wú)效調(diào)用。

          agoo調(diào)用方式優(yōu)化后,立刻剔除了無(wú)效調(diào)用,agoo受理率有了明顯提升。

          至此:我們總算能對(duì) agoo 受理失敗的真正原因做一個(gè)高大上的分析了。

          根據(jù)統(tǒng)計(jì):推送被 agoo 拒絕的主要原因是——用戶(hù)關(guān)閉了通知權(quán)限。同時(shí),我們對(duì) agoo 調(diào)用數(shù)據(jù)的進(jìn)一步分析發(fā)現(xiàn)——有部分用戶(hù)找不到對(duì)應(yīng)的設(shè)備。 優(yōu)化到此,我們猛然發(fā)現(xiàn)多了兩個(gè)問(wèn)題。

          那就繼續(xù)優(yōu)化唄:

          • 1)通知體驗(yàn)優(yōu)化,引導(dǎo)打開(kāi)通知權(quán)限;
          • 2)與agoo共建設(shè)備庫(kù),解決設(shè)備轉(zhuǎn)換失敗的問(wèn)題。

          這兩個(gè)優(yōu)化方向又是一片新天地,我們擇日再聊。

          8.2 廠商推送通道受理率優(yōu)化

          推送到達(dá) agoo ,分機(jī)型搭乘廠商“專(zhuān)列”,駛向下一站:用戶(hù)設(shè)備。

          這是推送經(jīng)歷的第二站。出站查票,發(fā)現(xiàn)竟然超員了。

          于是乎:我們每天有大量推送因?yàn)槌^(guò)廠商設(shè)定的限額被攔截。

          為什么會(huì)這樣呢?

          實(shí)際上:提供推送通道的廠商(沒(méi)錯(cuò),各手機(jī)廠商的自家推送通道良莠不齊),為了保證用戶(hù)體驗(yàn),會(huì)對(duì)每個(gè)應(yīng)用能夠推送的消息總量進(jìn)行限制。

          對(duì)于廠商而言,這個(gè)限制會(huì)根據(jù)推送的類(lèi)型和應(yīng)用的用戶(hù)規(guī)模設(shè)定——推送主要分為產(chǎn)品類(lèi)的推送和營(yíng)銷(xiāo)類(lèi)的推送。

          廠商推送通道對(duì)于不同類(lèi)型消息的限制是:

          • 1)對(duì)于產(chǎn)品類(lèi)推送,廠商會(huì)保證到達(dá);
          • 2)對(duì)于營(yíng)銷(xiāo)類(lèi)推送,廠商會(huì)進(jìn)行額度限制;
          • 3)未標(biāo)記的推送,默認(rèn)作為營(yíng)銷(xiāo)類(lèi)推送對(duì)待。

          我們剛好沒(méi)有對(duì)推送進(jìn)行標(biāo)記,因此觸發(fā)了廠商的推送限制。

          這對(duì)我們的用戶(hù)來(lái)說(shuō),會(huì)帶來(lái)困擾。閑魚(yú)的交易,很依賴(lài)買(mǎi)賣(mài)家之間的消息互動(dòng)。這部分消息是需要確保到達(dá)的。

          同樣:訂單類(lèi)的消息、用戶(hù)的關(guān)注,也需要保證推送給用戶(hù)。

          根據(jù)主流廠商的接口協(xié)議,我們將推送的消息分為以下幾類(lèi),并進(jìn)行相應(yīng)標(biāo)記:

          • 1)即時(shí)通訊消息;
          • 2)訂單狀態(tài)變化;
          • 3)用戶(hù)關(guān)注內(nèi)容;
          • 4)營(yíng)銷(xiāo)消息這幾類(lèi)。

          同時(shí),在業(yè)務(wù)上,我們也進(jìn)行了推送的治理——將用戶(hù)關(guān)注度不高的消息,取消推送,避免打擾。

          經(jīng)過(guò)這些優(yōu)化,因?yàn)槌^(guò)廠商限額而被攔截的推送實(shí)現(xiàn)了清零。

          8.3 Push點(diǎn)擊率優(yōu)化

          通過(guò)優(yōu)化agoo受理率、廠商受理率,我們解決了推送到達(dá)量的瓶頸。但即使消息被最終送達(dá),用戶(hù)到底點(diǎn)擊了沒(méi)有?這才是消息推送的根本意義所在。

          于是,在日常的開(kāi)發(fā)測(cè)試過(guò)程中,我們發(fā)現(xiàn)了推送的兩個(gè)體驗(yàn)問(wèn)題:

          • 1)用戶(hù)點(diǎn)擊Push有開(kāi)屏廣告;
          • 2)營(yíng)銷(xiāo)Push也有權(quán)限校驗(yàn),更換用戶(hù)登陸后無(wú)法點(diǎn)擊。

          對(duì)于開(kāi)屏廣告功能,我們?cè)黾恿薖ush點(diǎn)擊跳過(guò)廣告的能力。

          針對(duì)Push的權(quán)限校驗(yàn)功能,閑魚(yú)根據(jù)場(chǎng)景做了細(xì)分:

          • 1)涉及個(gè)人隱私的推送,保持權(quán)限校驗(yàn)不變;
          • 2)營(yíng)銷(xiāo)類(lèi)的推送,放開(kāi)權(quán)限校驗(yàn)。

          以上是點(diǎn)擊體驗(yàn)的優(yōu)化,我們還需要考慮用戶(hù)的點(diǎn)擊意愿。

          用戶(hù)點(diǎn)擊量與推送的曝光量、推送素材的有趣程度相關(guān)。推送的曝光量又和推送的到達(dá)量、推送的到達(dá)時(shí)機(jī)有關(guān)。

          具體的優(yōu)化手段是:

          • 1)在推送內(nèi)容上:我們需要優(yōu)化的是推送的時(shí)機(jī)和相應(yīng)的素材;
          • 2)在推送時(shí)機(jī)上:算法會(huì)根據(jù)用戶(hù)的偏好和個(gè)性化行為數(shù)據(jù),計(jì)算每個(gè)用戶(hù)的個(gè)性化推送時(shí)間,在用戶(hù)空閑的時(shí)間推送(避免在不合適的時(shí)間打擾用戶(hù),同時(shí)也能提升用戶(hù)看到推送的可能性)。
          • 3)在推送素材上:算法會(huì)根據(jù)素材的實(shí)時(shí)點(diǎn)擊反饋,對(duì)素材做實(shí)時(shí)賽馬。只發(fā)用戶(hù)感興趣的素材,提高用戶(hù)點(diǎn)擊意愿。

          9、實(shí)際優(yōu)化效果

          通過(guò)以上我們的分析和技術(shù)優(yōu)化手段,整體弱推送鏈路鏈路有了不錯(cuò)的提升,離線(xiàn)消息的到達(dá)率相對(duì)提升了兩位數(shù)。

          10、寫(xiě)在最后

          本篇主要和大家聊的是只是IM消息系統(tǒng)鏈路中的一環(huán)——弱感知鏈路的優(yōu)化,落地到到具體的業(yè)務(wù)也就是離線(xiàn)消息送達(dá)率問(wèn)題。

          整體IM消息系統(tǒng),還是一個(gè)比較復(fù)雜的領(lǐng)域。

          我們?cè)谙⑾到y(tǒng)的發(fā)展過(guò)程中,面臨著如下問(wèn)題:

          這些問(wèn)題,我們?cè)谝郧暗奈恼轮杏兴窒恚院笠矔?huì)陸續(xù)分享更多,敬請(qǐng)期待。

          附錄:相關(guān)資料

          [1] Android P正式版即將到來(lái):后臺(tái)應(yīng)用保活、消息推送的真正噩夢(mèng)

          [2] 一套高可用、易伸縮、高并發(fā)的IM群聊、單聊架構(gòu)方案設(shè)計(jì)實(shí)踐

          [3] 一套億級(jí)用戶(hù)的IM架構(gòu)技術(shù)干貨(上篇):整體架構(gòu)、服務(wù)拆分等

          [4] 一套億級(jí)用戶(hù)的IM架構(gòu)技術(shù)干貨(下篇):可靠性、有序性、弱網(wǎng)優(yōu)化等

          [5] 從新手到專(zhuān)家:如何設(shè)計(jì)一套億級(jí)消息量的分布式IM系統(tǒng)

          [6] 企業(yè)微信的IM架構(gòu)設(shè)計(jì)揭秘:消息模型、萬(wàn)人群、已讀回執(zhí)、消息撤回等

          [7] 融云技術(shù)分享:全面揭秘億級(jí)IM消息的可靠投遞機(jī)制

          [8] 移動(dòng)端IM中大規(guī)模群消息的推送如何保證效率、實(shí)時(shí)性?

          [9] 現(xiàn)代IM系統(tǒng)中聊天消息的同步和存儲(chǔ)方案探討

          [10] 新手入門(mén)一篇就夠:從零開(kāi)發(fā)移動(dòng)端IM

          [11] 移動(dòng)端IM開(kāi)發(fā)者必讀(一):通俗易懂,理解移動(dòng)網(wǎng)絡(luò)的“弱”和“慢”

          [12] 移動(dòng)端IM開(kāi)發(fā)者必讀(二):史上最全移動(dòng)弱網(wǎng)絡(luò)優(yōu)化方法總結(jié)

          [13] IM消息送達(dá)保證機(jī)制實(shí)現(xiàn)(一):保證在線(xiàn)實(shí)時(shí)消息的可靠投遞

          [14] IM消息送達(dá)保證機(jī)制實(shí)現(xiàn)(二):保證離線(xiàn)消息的可靠投遞

          [15] 零基礎(chǔ)IM開(kāi)發(fā)入門(mén)(一):什么是IM系統(tǒng)?

          [16] 零基礎(chǔ)IM開(kāi)發(fā)入門(mén)(二):什么是IM系統(tǒng)的實(shí)時(shí)性?

          [17] 零基礎(chǔ)IM開(kāi)發(fā)入門(mén)(三):什么是IM系統(tǒng)的可靠性?

          [18] 零基礎(chǔ)IM開(kāi)發(fā)入門(mén)(四):什么是IM系統(tǒng)的消息時(shí)序一致性?

          本文已同步發(fā)布于“即時(shí)通訊技術(shù)圈”公眾號(hào)。

          同步發(fā)布鏈接是:http://www.52im.net/thread-3748-1-1.html 

          posted @ 2021-11-17 12:24 Jack Jiang 閱讀(204) | 評(píng)論 (0)編輯 收藏

               摘要: 本文由公眾號(hào)“水滴與銀彈”號(hào)主Kaito原創(chuàng)分享,原題“搞懂異地多活,看這篇就夠了”,為使文章更好理解,即時(shí)通訊網(wǎng)收錄時(shí)有修訂。1、引言前幾天技術(shù)群里有群友問(wèn)我52im社區(qū)里有沒(méi)有IM分布式系統(tǒng)異地多活方面的文章,我仔細(xì)想了想,除了微信分享的幾篇文章里有提到容災(zāi)和異地多活(只是大致提過(guò),沒(méi)有詳細(xì)展開(kāi)),確實(shí)目前還沒(méi)有系統(tǒng)性的異地多活技術(shù)資料可供參考。...  閱讀全文

          posted @ 2021-11-10 15:18 Jack Jiang 閱讀(218) | 評(píng)論 (0)編輯 收藏

               摘要: 本文引用了ELab團(tuán)隊(duì)、騰訊大講堂兩個(gè)公眾號(hào)分享的文章內(nèi)容,引用內(nèi)容見(jiàn)文末參考資料,感謝原作者的無(wú)私分享。1、引言對(duì)于市面上主流的IM來(lái)說(shuō),跟二維碼有關(guān)的功能,比如掃碼加好友、掃碼登陸、掃碼加群等,都是很常見(jiàn)的。這是微信的掃碼登錄功能:這是微信的掃碼加好友功能: 二維碼技術(shù)使用起來(lái)很簡(jiǎn)單,本系列的前三篇文章也專(zhuān)門(mén)針對(duì)IM掃碼登錄這個(gè)功能做了詳細(xì)的分享,但本著學(xué)習(xí)技術(shù)不留死角的習(xí)慣,我認(rèn)為...  閱讀全文

          posted @ 2021-11-01 19:49 Jack Jiang 閱讀(158) | 評(píng)論 (0)編輯 收藏

               摘要: 本文由融云技術(shù)團(tuán)隊(duì)原創(chuàng)分享,原題“萬(wàn)字干貨:IM “消息”列表卡頓優(yōu)化實(shí)踐”,為使文章更好理解,內(nèi)容有修訂。1、引言隨著移動(dòng)互聯(lián)網(wǎng)的普及,無(wú)論是IM開(kāi)發(fā)者還是普通用戶(hù),IM即時(shí)通訊應(yīng)用在日常使用中都是必不可少的,比如:熟人社交的某信、IM活化石的某Q、企業(yè)場(chǎng)景的某釘?shù)龋瑤缀跏侨巳吮匮b。以下就是幾款主流的IM應(yīng)用(看首頁(yè)就知道是哪款,我就不廢話(huà)了):正...  閱讀全文

          posted @ 2021-10-26 14:41 Jack Jiang 閱讀(148) | 評(píng)論 (0)編輯 收藏

          本文由阿里閑魚(yú)技術(shù)團(tuán)隊(duì)有攸分享,原題“向消息延遲說(shuō)bybye:閑魚(yú)消息及時(shí)到達(dá)方案”,有修訂和改動(dòng),感謝作者的分享。

          1、引言

          IM消息作為閑魚(yú)用戶(hù)重要的交易咨詢(xún)工具,核心目標(biāo)有兩點(diǎn):

          • 1)第一是保證用戶(hù)的消息不丟失;
          • 2)第二是保證用戶(hù)的消息及時(shí)送達(dá)接收方。

          IM消息根據(jù)消息的接收方設(shè)備是否在線(xiàn),分為離線(xiàn)和在線(xiàn)推送。數(shù)據(jù)顯示目前閑魚(yú)每天有超過(guò)一半以上的IM消息是走在線(xiàn)通道的,而在線(xiàn)消息的到達(dá)率、及時(shí)性是直接影響用戶(hù)體驗(yàn)的。

          本文將根據(jù)閑魚(yú)IM消息系統(tǒng)在消息及時(shí)性方面的優(yōu)化實(shí)踐,詳細(xì)分析了IM在線(xiàn)通道面臨的各種技術(shù)問(wèn)題,并通過(guò)相應(yīng)的技術(shù)手段來(lái)優(yōu)化從而保證用戶(hù)消息的及時(shí)到達(dá)。

          PS:如果您對(duì)IM消息可靠性還沒(méi)有概念,建議先閱讀這篇入門(mén)文章《零基礎(chǔ)IM開(kāi)發(fā)入門(mén)(二):什么是IM系統(tǒng)的實(shí)時(shí)性?》。

          學(xué)習(xí)交流:

          - 即時(shí)通訊/推送技術(shù)開(kāi)發(fā)交流5群:215477170 [推薦]

          - 移動(dòng)端IM開(kāi)發(fā)入門(mén)文章:《新手入門(mén)一篇就夠:從零開(kāi)發(fā)移動(dòng)端IM

          - 開(kāi)源IM框架源碼:https://github.com/JackJiang2011/MobileIMSDK

          本文同步發(fā)布于:http://www.52im.net/thread-3726-1-1.html

          2、系列文章

          本文是系列文章的第5篇,總目錄如下:

          3、當(dāng)前面臨的問(wèn)題

          3.1 端內(nèi)長(zhǎng)連接中斷

          在IM場(chǎng)景中,用戶(hù)與云端通信頻繁,且為了實(shí)現(xiàn)用戶(hù)的消息及時(shí)到達(dá),往往采用云端下推消息的方式觸達(dá)用戶(hù),所以用戶(hù)在線(xiàn)時(shí)設(shè)備與云端會(huì)維持一條TCP長(zhǎng)連接通道,可以更輕量級(jí)的與服務(wù)端進(jìn)行交互,現(xiàn)代IM即時(shí)通訊的下行消息都是通過(guò)長(zhǎng)連下發(fā)的。

          當(dāng)前閑魚(yú)IM消息系統(tǒng)使用的是ACCS長(zhǎng)連接,ACCS是淘寶無(wú)線(xiàn)提供的全雙工、低延時(shí)、高安全的通道服務(wù)。

          但由于用戶(hù)設(shè)備網(wǎng)絡(luò)狀態(tài)的不確定性,可能會(huì)發(fā)生各種各樣的網(wǎng)絡(luò)異常情況導(dǎo)致ACCS長(zhǎng)連接通道中斷。而長(zhǎng)連接一旦意外中斷,就會(huì)導(dǎo)致用戶(hù)無(wú)法及時(shí)收到在線(xiàn)消息。

          針對(duì)這個(gè)問(wèn)題,我們需要盡可能及時(shí)的感知到長(zhǎng)連中斷并嘗試重連。具體的優(yōu)化思路會(huì)在本文后面的內(nèi)容中分享。

          3.2 下推的消息未達(dá)

          感知長(zhǎng)連中斷并重連只能在大多數(shù)時(shí)間保證長(zhǎng)連接的有效性,但是在長(zhǎng)連接無(wú)效或不穩(wěn)定期間下推的消息客戶(hù)端可能根本收不到。

          簡(jiǎn)單說(shuō)就是僅僅有重連機(jī)制無(wú)法保證下行消息必達(dá),可能有以下場(chǎng)景導(dǎo)致下行消息失敗:

          • 1)服務(wù)端發(fā)送下行消息時(shí)長(zhǎng)連暢通,消息在傳輸路上通道斷掉,客戶(hù)端無(wú)法收到;
          • 2)設(shè)備的在線(xiàn)狀態(tài)存在延遲,服務(wù)端下行消息時(shí)認(rèn)為設(shè)備在線(xiàn),實(shí)際上設(shè)備已經(jīng)離線(xiàn),無(wú)法收到;
          • 3)客戶(hù)端收到了下行消息,但端上后續(xù)處理失敗(比如落庫(kù)失敗,消息沒(méi)有成功展示給用戶(hù))。

          我們通過(guò)數(shù)據(jù)埋點(diǎn)統(tǒng)計(jì)得出,ACCS長(zhǎng)連接的下行成功率在97%左右。

          ACCS長(zhǎng)連接的下行成功率的統(tǒng)計(jì)方法如下:

          ACCS下行成功率 = 通過(guò)ACCS成功下行且客戶(hù)端收到的消息量 / 服務(wù)端認(rèn)為通過(guò)ACCS成功下行的消息量

          有心急的同學(xué)就要問(wèn)了,丟了3%的消息嗎?

          并沒(méi)有!這3%的消息不會(huì)丟失,只是不保證及時(shí)觸達(dá)給用戶(hù)。

          我們的消息同步模型是推拉結(jié)合模式,在用戶(hù)拉取消息時(shí)會(huì)拉取到設(shè)備當(dāng)前位點(diǎn)與服務(wù)端最新位點(diǎn)的所有消息,ACCS下行失敗的消息會(huì)通過(guò)主動(dòng)拉模式獲取到,但客戶(hù)端主動(dòng)拉取消息的觸發(fā)時(shí)機(jī)有限。

          當(dāng)前客戶(hù)端主動(dòng)拉取消息的觸發(fā)時(shí)機(jī)主要有以下幾個(gè):

          • 1)用戶(hù)冷啟動(dòng)app,主動(dòng)同步消息;
          • 2)用戶(hù)主動(dòng)下拉刷新;
          • 3)app后臺(tái)切換前臺(tái);
          • 4)收到一條推送消息,客戶(hù)端發(fā)現(xiàn)新消息的位點(diǎn)跟本地最新的位點(diǎn)有g(shù)ap,觸發(fā)同步。

          可見(jiàn):上述主動(dòng)同步消息的觸發(fā)很大程度上依賴(lài)用戶(hù)行為或者有沒(méi)有收到新消息,難以保證消息及時(shí)到達(dá)。

          如果是用戶(hù)高頻打開(kāi)的IM軟件,這樣也不會(huì)有太大的問(wèn)題。但是閑魚(yú)app的活躍度較低,有時(shí)候甚至依賴(lài)IM消息拉活,而且一條延遲的消息觸達(dá)可能導(dǎo)致用戶(hù)錯(cuò)過(guò)一筆交易,閑魚(yú)消息不允許有這樣的延遲發(fā)生。

          基于上述分析,我們先描述一個(gè)數(shù)據(jù)指標(biāo)來(lái)反映現(xiàn)狀。

          通過(guò)上面的描述可知:ACCS消息并不全都是推下來(lái)的,也可能是主動(dòng)拉下來(lái)的。如果是推,必定可以及時(shí)到達(dá);如果是拉,則受限于用戶(hù)行為。

          拉的這部分消息,我們定義為ACCS消息補(bǔ)償?shù)竭_(dá),然后計(jì)算ACCS消息補(bǔ)償?shù)竭_(dá)耗時(shí),消息范圍限定為服務(wù)端ACCS成功下行但是客戶(hù)端通過(guò)主動(dòng)拉取同步到的消息,以往的版本這個(gè)數(shù)據(jù)在60分鐘左右。

          注意:這個(gè)數(shù)據(jù)并不是消息觸達(dá)到用戶(hù)的耗時(shí),因?yàn)槿绻诰€(xiàn)轉(zhuǎn)離線(xiàn)觸達(dá),拉取到消息的時(shí)間取決于用戶(hù)行為(用戶(hù)何時(shí)打開(kāi)了app),但這個(gè)數(shù)據(jù)也能大致反映在線(xiàn)消息的到達(dá)延遲狀況。

          ACCS長(zhǎng)連接的消息補(bǔ)償?shù)竭_(dá)耗時(shí)的統(tǒng)計(jì)方法如下:

          ACCS消息補(bǔ)償?shù)竭_(dá)耗時(shí) = 客戶(hù)端通過(guò)拉獲取到ACCS消息的時(shí)間 - 服務(wù)端ACCS下行時(shí)間

          接下來(lái)本文將從長(zhǎng)連接的重連和未達(dá)消息重發(fā)兩個(gè)方面詳細(xì)講述我們是如何優(yōu)化在線(xiàn)通道穩(wěn)定性的,從而優(yōu)化并保證消息的及時(shí)到達(dá)。

          4、優(yōu)化手段1:增加長(zhǎng)連接重連機(jī)制

          4.1 長(zhǎng)連接為什么會(huì)中斷?

          有因必有果,我們先來(lái)分析下有哪些原因會(huì)導(dǎo)致連接中斷。

          對(duì)于IM這種場(chǎng)景下來(lái)說(shuō),通常可能有以下原因:

          • 1)用戶(hù)設(shè)備斷網(wǎng);
          • 2)設(shè)備發(fā)生了網(wǎng)絡(luò)切換;
          • 3)設(shè)備處于弱網(wǎng)環(huán)境,網(wǎng)絡(luò)不穩(wěn)定;
          • 4)設(shè)備網(wǎng)絡(luò)正常,TCP連接由于NAT超時(shí)導(dǎo)致連接被運(yùn)營(yíng)商中斷。

          對(duì)于APP來(lái)說(shuō),如果是用戶(hù)操作導(dǎo)致網(wǎng)絡(luò)狀態(tài)變化的情況,會(huì)有網(wǎng)絡(luò)狀態(tài)變化事件通知,這種情況可以監(jiān)聽(tīng)事件并主動(dòng)嘗試重連。但現(xiàn)實(shí)中的大多數(shù)情況都是“意料之外”(正如上面列舉的這些斷網(wǎng)可能性一樣)。

          那么既然“意料之外”的斷網(wǎng)無(wú)法預(yù)知,技術(shù)上可以如何有效的感知到各種異常狀況呢?

          PS:如果要透徹理解斷網(wǎng)、弱網(wǎng)、TCP鏈接有效性,并不是本文能講的清楚的,可以參照下面的資料深入理解一下,值得好好學(xué)習(xí)。

          關(guān)于TCP鏈接本身的有效性問(wèn)題,可以讀以下兩篇:

          1. 為何基于TCP協(xié)議的移動(dòng)端IM仍然需要心跳保活機(jī)制?
          2. 不為人知的網(wǎng)絡(luò)編程(十二):徹底搞懂TCP協(xié)議層的KeepAlive保活機(jī)制

          關(guān)于移動(dòng)網(wǎng)絡(luò)的復(fù)雜性問(wèn)題,可以從以下幾篇入門(mén)的科普文章學(xué)習(xí)一下:

          1. IM開(kāi)發(fā)者的零基礎(chǔ)通信技術(shù)入門(mén)(十一):為什么WiFi信號(hào)差?一文即懂!
          2. IM開(kāi)發(fā)者的零基礎(chǔ)通信技術(shù)入門(mén)(十二):上網(wǎng)卡頓?網(wǎng)絡(luò)掉線(xiàn)?一文即懂!
          3. IM開(kāi)發(fā)者的零基礎(chǔ)通信技術(shù)入門(mén)(十三):為什么手機(jī)信號(hào)差?一文即懂!
          4. IM開(kāi)發(fā)者的零基礎(chǔ)通信技術(shù)入門(mén)(十四):高鐵上無(wú)線(xiàn)上網(wǎng)有多難?一文即懂!

          關(guān)于移動(dòng)弱網(wǎng)帶來(lái)的各種問(wèn)題、優(yōu)化方案等,可以通過(guò)以下幾篇系統(tǒng)學(xué)習(xí)一下:

          1. 現(xiàn)代移動(dòng)端網(wǎng)絡(luò)短連接的優(yōu)化手段總結(jié):請(qǐng)求速度、弱網(wǎng)適應(yīng)、安全保障
          2. 移動(dòng)端IM開(kāi)發(fā)者必讀(一):通俗易懂,理解移動(dòng)網(wǎng)絡(luò)的“弱”和“慢”
          3. 移動(dòng)端IM開(kāi)發(fā)者必讀(二):史上最全移動(dòng)弱網(wǎng)絡(luò)優(yōu)化方法總結(jié)
          4. 百度APP移動(dòng)端網(wǎng)絡(luò)深度優(yōu)化實(shí)踐分享(三):移動(dòng)端弱網(wǎng)優(yōu)化篇

          4.2 心跳檢測(cè)機(jī)制

          像大多數(shù)鏈路保活場(chǎng)景一樣,IM這種場(chǎng)景下最有效的檢測(cè)手段就是心跳檢測(cè)(如果你對(duì)TCP鏈路保活還沒(méi)有什么概念,建議先讀《為何基于TCP協(xié)議的移動(dòng)端IM仍然需要心跳保活機(jī)制?)。

          原理就是:客戶(hù)端通過(guò)定時(shí)發(fā)送心跳包,服務(wù)端收到心跳包后再反饋給客戶(hù)端,通過(guò)客戶(hù)端和服務(wù)端這一來(lái)一去的配合,就可以實(shí)現(xiàn)客戶(hù)服和服務(wù)端各自都能感知到連接是否中斷。

          從及時(shí)性效果來(lái)看:心跳間隔越短越好,而頻繁的心跳檢測(cè)勢(shì)必會(huì)帶來(lái)用戶(hù)流量以及電量的損耗,所以我們的實(shí)現(xiàn)目標(biāo)是如何盡可能少的心跳檢測(cè)而又盡量及時(shí)地感知到長(zhǎng)連中斷的意外情況。

          狀態(tài)機(jī)+消息心跳隊(duì)列:

          在心跳協(xié)議設(shè)計(jì)上,要注意心跳包的核心目標(biāo)是檢測(cè)長(zhǎng)連通道是否暢通,客戶(hù)端主動(dòng)上行心跳包且能收到服務(wù)端回包,就認(rèn)為長(zhǎng)連通道健康。所以心跳的上行消息以及回包的數(shù)據(jù)包應(yīng)盡可能小。一般來(lái)說(shuō),通過(guò)協(xié)議頭標(biāo)識(shí)心跳包及響應(yīng)即可(這樣就能節(jié)省協(xié)議包大小)。

          PS:關(guān)于心跳機(jī)制的入門(mén)文章可以詳讀《一文讀懂即時(shí)通訊應(yīng)用中的網(wǎng)絡(luò)心跳包機(jī)制:作用、原理、實(shí)現(xiàn)思路等》。

          4.3 心跳策略

          心跳策略是實(shí)現(xiàn)我們上述目標(biāo)的核心機(jī)制,本文僅簡(jiǎn)單列舉幾種心跳策略。

          比如以下這幾種:

          • 1)短心跳檢測(cè) 初始狀態(tài)連續(xù) ping 3次 收到 ACK 后,可以認(rèn)為進(jìn)入穩(wěn)定狀態(tài);
          • 2)常規(guī)固定時(shí)長(zhǎng)心跳(根據(jù)app狀態(tài)不同,頻率可調(diào)Mid+,Mid-, Long);
          • 3)自適應(yīng)心跳 根據(jù)設(shè)備網(wǎng)絡(luò)狀態(tài)變化自動(dòng)適應(yīng)的心跳間隔;
          • 4)冗余心跳,app后臺(tái)切前臺(tái),主動(dòng)心跳一次。

          關(guān)于心跳策略的詳細(xì)設(shè)計(jì)甚至可以單獨(dú)寫(xiě)一篇文章,有興趣的同學(xué)可以閱讀以下推薦的文章繼續(xù)深入研究。

          5、優(yōu)化手段2:消息ACK應(yīng)答與重發(fā)機(jī)制

          5.1 概述

          為了解決上面的問(wèn)題,我們同時(shí)也引入了消息ACK應(yīng)答與重發(fā)機(jī)制。

          整體思路是:客戶(hù)端在收到ACCS消息并處理成功后,給服務(wù)端回一個(gè)ACK應(yīng)答包,服務(wù)端下發(fā)ACCS消息時(shí)將消息加入重試隊(duì)列,收到ACK應(yīng)答包后更新消息到達(dá)狀態(tài),并終止重試。

          整體設(shè)計(jì)流程圖如下:

          該方案的難點(diǎn)即重試處理器的實(shí)現(xiàn)設(shè)計(jì),接下來(lái)我們將重點(diǎn)講述這部分的詳細(xì)設(shè)計(jì)。

          5.2 重試隊(duì)列存儲(chǔ)設(shè)計(jì)

          我們采用阿里云表格存儲(chǔ)TimeLine模型來(lái)存儲(chǔ)下行消息的到達(dá)狀態(tài)。Timeline 模型是針對(duì)消息數(shù)據(jù)場(chǎng)景所設(shè)計(jì)的數(shù)據(jù)模型,它能滿(mǎn)足消息數(shù)據(jù)場(chǎng)景對(duì)消息保序、海量消息存儲(chǔ)、實(shí)時(shí)同步的特殊需求,在IM、Feed流等消息場(chǎng)景應(yīng)用廣泛。(關(guān)于TimeLine模型,這里有篇詳細(xì)的文章可以學(xué)習(xí)一下《現(xiàn)代IM系統(tǒng)中聊天消息的同步和存儲(chǔ)方案探討

          我們給每個(gè)用戶(hù)設(shè)備定義一個(gè)TimeLine,timeline-id定義為userId_deviceId,sequenceId自定義為消息位點(diǎn)。

          存儲(chǔ)結(jié)構(gòu)如下:

          每通過(guò)ACCS成功下行一條消息,則插入到接收用戶(hù)設(shè)備的TimeLine中,收到ACK后根據(jù)消息id更新消息到達(dá)狀態(tài)。

          同時(shí)由于重試動(dòng)作只發(fā)生在下行消息后較短的一段時(shí)間內(nèi),所以我們?cè)O(shè)置一個(gè)比較短的全局過(guò)期時(shí)間即可,避免數(shù)據(jù)膨脹。

          5.3 延遲重試設(shè)計(jì)

          如上圖所示:

          • 1)每通過(guò)ACCS下發(fā)一條消息,先插入到Timeline中,初始狀態(tài)為未達(dá),然后生產(chǎn)一條延遲N秒的延遲消息;
          • 2)每次消費(fèi)到延遲消息后,讀取tablestore中該消息的到達(dá)狀態(tài),如到達(dá)則終止延遲,否則繼續(xù);
          • 3)每次重試先判斷設(shè)備是否在線(xiàn),如果設(shè)備不在線(xiàn),轉(zhuǎn)發(fā)離線(xiàn)通道并終止重試,如果設(shè)備在線(xiàn),則重推未到達(dá)的消息,并再次延遲N秒消費(fèi);
          • 4)每條消息的重試生命周期中用的同一條延遲消息,最多重試消費(fèi)M次,超過(guò)次數(shù)不再重試并打日志埋點(diǎn)(后續(xù)可以監(jiān)控這種情況并基于這個(gè)數(shù)據(jù)進(jìn)行優(yōu)化)。

          5.4 延遲重發(fā)策略

          延遲重發(fā)策略是指在重發(fā)流程中,如何選擇合適的延遲時(shí)間來(lái)使得重發(fā)的效率最高。

          不同用戶(hù)在不同時(shí)間、地點(diǎn)所處的網(wǎng)絡(luò)環(huán)境差別較大,網(wǎng)絡(luò)恢復(fù)到穩(wěn)定態(tài)所需要的時(shí)間也有差異,需要選用合適的延遲策略來(lái)保證重發(fā)效率。

          最優(yōu)的延遲策略的目標(biāo)是在最短的時(shí)間內(nèi),使用最少的重發(fā)次數(shù)將消息投遞成功。以下是幾種可選的方案。

          5.4.1)固定延遲時(shí)間:

          要想找到最優(yōu)的延遲策略,必須從數(shù)據(jù)中通過(guò)分析得到答案,天馬行空的想象往往離實(shí)際相差甚遠(yuǎn)。

          我們先采用固定的延遲時(shí)間(10s)最大重試6次來(lái)分析一波數(shù)據(jù):

          通過(guò)這組數(shù)據(jù)可以看到:有約85%的消息在40s內(nèi)重發(fā)可以投遞成功,還有12%的消息在達(dá)到最大重試次數(shù)后依舊沒(méi)有收到ACK。在4次重試之后,第5次成功只有2.03%,第6次只有0.92%,繼續(xù)重發(fā)的收益已經(jīng)變得很低。

          6次以后還有部分消息沒(méi)有收到ACK,這部分消息如果用固定延遲時(shí)間策略,性?xún)r(jià)比很低,頻繁重發(fā)浪費(fèi)系統(tǒng)資源,我們需要繼續(xù)改進(jìn)策略。

          5.4.2)固定延遲+固定步長(zhǎng)遞增:

          考慮到部分用戶(hù)的網(wǎng)絡(luò)短時(shí)間無(wú)法恢復(fù),頻繁的短間隔重發(fā)價(jià)值不大,我們采用4次固定短間隔延遲N秒后,每次延遲時(shí)間都是上一次延遲時(shí)間遞增固定步長(zhǎng)M秒的策略。直到收到ACK、用戶(hù)設(shè)備離線(xiàn)或者達(dá)到了最大延遲時(shí)間MAX(N)。

          這種策略一定程度上可以解決固定延遲時(shí)間重發(fā)策略的問(wèn)題,但如果用戶(hù)短時(shí)間網(wǎng)絡(luò)無(wú)法恢復(fù),每次重發(fā)都要重新遞增,也不是一種最優(yōu)解。

          5.4.3)自適應(yīng)延遲:

          設(shè)計(jì)流程圖:

          如上圖:我們最終衍生出了自適應(yīng)延遲策略。

          自適應(yīng)延遲是指:根據(jù)用戶(hù)的網(wǎng)絡(luò)狀況,采取自動(dòng)調(diào)整的延遲時(shí)間,以期望達(dá)到最高的重發(fā)效率。

          具體是:新消息先通過(guò)4次固定N秒的短延遲來(lái)探測(cè)設(shè)備的網(wǎng)絡(luò)狀況,一旦網(wǎng)絡(luò)恢復(fù),我們將設(shè)備的N值清空(設(shè)備N(xiāo)值是指根據(jù)上幾次重發(fā)經(jīng)驗(yàn),當(dāng)前設(shè)備網(wǎng)絡(luò)能回復(fù)ACK所需要的最短時(shí)間,默認(rèn)情況該值為空,代表用戶(hù)設(shè)備網(wǎng)絡(luò)正常)。4次重發(fā)后依舊收不到ACK,我們嘗試讀取設(shè)備N(xiāo)值,如果為空,則取初始值,以后每次延遲都遞增固定步長(zhǎng)M,并在重發(fā)后更新當(dāng)前設(shè)備的N值,直到消息收到ACK或者達(dá)到了最大延遲時(shí)間MAX(N)。

          5.5 新老版本兼容性

          需要注意的是老版本的app是不會(huì)回ACK的,如果下發(fā)給老版本設(shè)備的消息也加入重試隊(duì)列,那此類(lèi)消息將一直重試到最大次數(shù)才會(huì)終止,無(wú)端消耗資源。

          所以我們?cè)O(shè)計(jì)在ACCS長(zhǎng)連建立之后,客戶(hù)端主動(dòng)上行一條設(shè)備信息,其中包含app的版本號(hào),服務(wù)端存儲(chǔ)一定時(shí)間,在將消息加入重試隊(duì)列之前,先校驗(yàn)接收者設(shè)備app的版本號(hào),符合要求再加入重試隊(duì)列。

          6、 最終優(yōu)化后的效果

          消息重連重發(fā)方案上線(xiàn)后,我們上面定義的指標(biāo) ACCS補(bǔ)償?shù)竭_(dá)時(shí)間 從60分鐘大幅降低至15分鐘,降幅達(dá)75%。

          從而印證了我們的技術(shù)分析,同時(shí)用戶(hù)有關(guān)消息延遲的輿情反饋大幅下降,可見(jiàn)消息重發(fā)機(jī)制對(duì)保證用戶(hù)消息及時(shí)到達(dá)成效顯著。

          7、未來(lái)展望

          消息在線(xiàn)通道的穩(wěn)定性?xún)?yōu)化至此已告一段落,未來(lái)我們將繼續(xù)優(yōu)化閑魚(yú)消息的使用體驗(yàn),包括基礎(chǔ)功能的完善以及基礎(chǔ)體驗(yàn)的提升。

          基礎(chǔ)功能方面:我們?cè)诮诘陌姹局幸呀?jīng)支持了消息撤回、草稿功能,后續(xù)將逐步支持發(fā)送定位,會(huì)話(huà)分組、備注,消息搜索等功能。

          基礎(chǔ)體驗(yàn)方面:我們對(duì)消息的UI樣式做了優(yōu)化升級(jí),并優(yōu)化了app消息tab頁(yè)的cpu及內(nèi)存使用,后續(xù)將繼續(xù)從流量、電量、性能方面繼續(xù)優(yōu)化消息的使用體驗(yàn)。

          附錄:參考資料

          [1] 為何基于TCP協(xié)議的移動(dòng)端IM仍然需要心跳保活機(jī)制?

          [2] 不為人知的網(wǎng)絡(luò)編程(十二):徹底搞懂TCP協(xié)議層的KeepAlive保活機(jī)制

          [3] 現(xiàn)代IM系統(tǒng)中聊天消息的同步和存儲(chǔ)方案探討

          [4] 現(xiàn)代移動(dòng)端網(wǎng)絡(luò)短連接的優(yōu)化手段總結(jié):請(qǐng)求速度、弱網(wǎng)適應(yīng)、安全保障

          [5] 移動(dòng)端IM開(kāi)發(fā)者必讀(二):史上最全移動(dòng)弱網(wǎng)絡(luò)優(yōu)化方法總結(jié)

          [6] IM開(kāi)發(fā)者的零基礎(chǔ)通信技術(shù)入門(mén)(十二):上網(wǎng)卡頓?網(wǎng)絡(luò)掉線(xiàn)?一文即懂!

          [7] IM開(kāi)發(fā)者的零基礎(chǔ)通信技術(shù)入門(mén)(十三):為什么手機(jī)信號(hào)差?一文即懂!

          [8] 移動(dòng)端IM實(shí)踐:實(shí)現(xiàn)Android版微信的智能心跳機(jī)制

          [9] 融云技術(shù)分享:融云安卓端IM產(chǎn)品的網(wǎng)絡(luò)鏈路保活技術(shù)實(shí)踐

          [10] Web端即時(shí)通訊實(shí)踐干貨:如何讓你的WebSocket斷網(wǎng)重連更快速?

          本文已同步發(fā)布于“即時(shí)通訊技術(shù)圈”公眾號(hào)。

          同步發(fā)布鏈接是:http://www.52im.net/thread-3726-1-1.html

          posted @ 2021-10-19 23:05 Jack Jiang 閱讀(263) | 評(píng)論 (0)編輯 收藏

               摘要: 本文由作者“阿寶哥”分享,原題“你不知道的 WebSocket”,有修訂和改動(dòng)。1、引言本文將從基本概念、技術(shù)原理、常見(jiàn)易錯(cuò)常識(shí)、動(dòng)手實(shí)踐等多個(gè)方面入手,萬(wàn)字長(zhǎng)文,帶你一起全方位探索 WebSocket 技術(shù)。閱讀完本文,你將了解以下內(nèi)容:1)了解 WebSocket 的誕生背景、WebSocket 是什么及它的優(yōu)點(diǎn);2)了解 WebSocket 含...  閱讀全文

          posted @ 2021-10-11 14:35 Jack Jiang 閱讀(173) | 評(píng)論 (0)編輯 收藏

               摘要: 本文由阿里閑魚(yú)技術(shù)團(tuán)隊(duì)景松分享,原題“到達(dá)率99.9%:閑魚(yú)消息在高速上換引擎(集大成)”,有修訂和改動(dòng),感謝作者的分享。1、引言在2020年年初的時(shí)候接手了閑魚(yú)的IM即時(shí)消息系統(tǒng),當(dāng)時(shí)的消息存在各種問(wèn)題,網(wǎng)上的用戶(hù)輿情也是接連不斷。典型的問(wèn)題,比如:1)“聊天消息經(jīng)常丟失”;2)“消息用戶(hù)頭像亂了”;3)“訂單狀...  閱讀全文

          posted @ 2021-09-26 14:47 Jack Jiang 閱讀(224) | 評(píng)論 (0)編輯 收藏

          本文由阿里閑魚(yú)技術(shù)團(tuán)隊(duì)今朝、有攸分享,本次有修訂。

          1、引言

          閑魚(yú)即時(shí)消息系統(tǒng)歷經(jīng)數(shù)代迭代,目前已能穩(wěn)定的支撐億級(jí)消息體量。

          在此消息系統(tǒng)的建設(shè)過(guò)程中,我們經(jīng)歷了從簡(jiǎn)單到復(fù)雜、從困擾到破局,每一次的技術(shù)改變都是為了更好的解決當(dāng)下業(yè)務(wù)所面臨的問(wèn)題。

          本文分享的是閑魚(yú)即時(shí)消息系統(tǒng)架構(gòu)從零開(kāi)始的技術(shù)變遷之路,以期更多的同行們?cè)诖嘶A(chǔ)上汲取經(jīng)驗(yàn),得到有價(jià)值的啟發(fā)。

          學(xué)習(xí)交流:

          - 即時(shí)通訊/推送技術(shù)開(kāi)發(fā)交流5群:215477170 [推薦]

          - 移動(dòng)端IM開(kāi)發(fā)入門(mén)文章:《新手入門(mén)一篇就夠:從零開(kāi)發(fā)移動(dòng)端IM

          - 開(kāi)源IM框架源碼:https://github.com/JackJiang2011/MobileIMSDK

          本文同步發(fā)布于:http://www.52im.net/thread-3699-1-1.html )

          2、系列文章

          本文是系列文章的第3篇,總目錄如下:

          1. 阿里IM技術(shù)分享(一):企業(yè)級(jí)IM王者——釘釘在后端架構(gòu)上的過(guò)人之處
          2. 阿里IM技術(shù)分享(二):閑魚(yú)IM基于Flutter的移動(dòng)端跨端改造實(shí)踐
          3. 阿里IM技術(shù)分享(三):閑魚(yú)億級(jí)IM消息系統(tǒng)的架構(gòu)演進(jìn)之路》(* 本文
          4. 阿里IM技術(shù)分享(四):閑魚(yú)億級(jí)IM消息系統(tǒng)的可靠性投遞技術(shù)實(shí)踐》(* 稍后發(fā)布

          3、1.0版:業(yè)務(wù)初創(chuàng)期、最小化可用

          3.1 技術(shù)背景

          2014年啟動(dòng)閑置交易獨(dú)立APP “閑魚(yú)”,一期構(gòu)建完成APP主鏈路,包含商品:發(fā)布→搜索→商品詳情→IM會(huì)話(huà)→交易

          作為初創(chuàng)app,業(yè)務(wù)需盡快上線(xiàn)驗(yàn)證效果,技術(shù)建設(shè)上需要完成閑魚(yú)消息從無(wú)到有的系統(tǒng)搭建。

          3.2 技術(shù)方案

          作為即時(shí)通訊系統(tǒng),最小化能力包含:

          • 1)消息存儲(chǔ):會(huì)話(huà)、摘要、消息;
          • 2)消息同步:推、拉;
          • 3)消息通道:長(zhǎng)連接、廠商推送。

          與一般IM會(huì)話(huà)模型不同的是,閑魚(yú)會(huì)話(huà)以商品為主體,“人+人+商品”為要素構(gòu)建會(huì)話(huà)。

          因會(huì)話(huà)模型的差異,淘系已有的消息系統(tǒng),短期內(nèi)無(wú)法滿(mǎn)足業(yè)務(wù)需求,而閑魚(yú)完全自建消息系統(tǒng)耗時(shí)巨大。

          為了保障業(yè)務(wù)高效上線(xiàn),技術(shù)選型上最大化復(fù)用已有系統(tǒng)能力,避免重復(fù)造輪子。

          所以,我們的技術(shù)方案是:

          • 1)數(shù)據(jù)模型與底層存儲(chǔ)依賴(lài)淘系私信體系進(jìn)行建設(shè);
          • 2)消息數(shù)據(jù)獲取上,客戶(hù)端全量從服務(wù)端拉取消息數(shù)據(jù);
          • 3)通訊協(xié)議使用來(lái)往SDK及mtop。

          總體架構(gòu)如下圖,以此模式完成快速交付保障了業(yè)務(wù)最小化可用:

          4、2.0版:用戶(hù)量增速快、需要重建消息系統(tǒng)

          4.1 技術(shù)背景

          閑魚(yú)用戶(hù)量正快速突破100萬(wàn),即時(shí)消息服務(wù)的調(diào)用量暴漲。在這樣的背景下,用戶(hù)反饋消息數(shù)據(jù)獲取的卡頓、白屏成為常態(tài),大量的消息Push發(fā)送下,系統(tǒng)告警頻發(fā)。

          造成這些問(wèn)題的原因:1.0版的架構(gòu)模式下,獲取消息數(shù)據(jù)全量拉模式,客戶(hù)端純UI不做數(shù)據(jù)存儲(chǔ)。

          具體就是:

          • 1)當(dāng)用戶(hù)需要查看消息數(shù)據(jù)時(shí),數(shù)據(jù)拉取成功與否取決于網(wǎng)絡(luò)、數(shù)據(jù)訪(fǎng)問(wèn)速度,偶發(fā)性的造成卡頓、白屏;
          • 2)中心化的數(shù)據(jù)存儲(chǔ),讀遠(yuǎn)大于寫(xiě),高并發(fā)下,服務(wù)端負(fù)載過(guò)大。

          針對(duì)第2)點(diǎn):比如1W個(gè)用戶(hù)同時(shí)在線(xiàn)聊天,按照當(dāng)前架構(gòu)并發(fā)拉取全量消息,估算5萬(wàn)QPS。不妨假設(shè),同時(shí)在線(xiàn)聊天用戶(hù)數(shù)10萬(wàn)時(shí),對(duì)服務(wù)端壓力可想而知。

          4.2 技術(shù)方案

          基于上述問(wèn)題,我們決定重建消息系統(tǒng)架構(gòu),以應(yīng)對(duì)未來(lái)更大的用戶(hù)增量。

          回歸到IM系統(tǒng)的核心功能:

          4.2.1)消息存儲(chǔ)模型:

          • 1)會(huì)話(huà)模型:由owner、itemid、user、sessionType 來(lái)標(biāo)識(shí)唯一會(huì)話(huà),增加擴(kuò)展屬性支持個(gè)性化;
          • 2)摘要模型:作為用戶(hù)會(huì)話(huà)視圖,同一會(huì)話(huà)的不同用戶(hù)可個(gè)性化呈現(xiàn),由userid、sid標(biāo)識(shí)唯一摘要;
          • 3)消息模型:由sender、消息內(nèi)容、消息版本、sid組成。sid+消息版本唯一確定一條消息;
          • 4)指令模型:是一種雙端約定,由服務(wù)端下發(fā),客戶(hù)端執(zhí)行的指令集。如免打擾指令、刪除指令等。

          4.2.2)消息通道:

          1)在線(xiàn)通道:使用淘寶無(wú)線(xiàn)ACCS長(zhǎng)連接提供的全雙工、低延時(shí)、高安全的通道服務(wù);

          2)離線(xiàn)通道:使用淘寶消息推送平臺(tái)AGOO. 其屏蔽了各主流廠商對(duì)接的復(fù)雜度,直接對(duì)業(yè)務(wù)系統(tǒng)提供服務(wù)。

          4.2.3)消息同步模型:

          1)客戶(hù)端建立數(shù)據(jù)庫(kù),存儲(chǔ)消息數(shù)據(jù):當(dāng)消息數(shù)據(jù)存儲(chǔ)在本地設(shè)備上,消息同步從全量拉取優(yōu)化為全量+增量同步結(jié)合的模式。

          增量和全量同步具體指的是:

          • a. 增量同步:客戶(hù)端存儲(chǔ)消息位點(diǎn)信息,通過(guò)與服務(wù)端最新位點(diǎn)比較,僅同步增量消息;
          • b. 全量同步:當(dāng)用戶(hù)卸載重裝或位點(diǎn)gap過(guò)大時(shí),客戶(hù)端全量拉取歷史消息數(shù)據(jù),進(jìn)行端上數(shù)據(jù)重建。

          2)服務(wù)端建設(shè)個(gè)人消息域環(huán)(收件箱模型):以和客戶(hù)端進(jìn)行增量數(shù)據(jù)同步。同時(shí),1.0版本架構(gòu)中存在的讀多寫(xiě)少的問(wèn)題,通過(guò)個(gè)人域環(huán)的寫(xiě)擴(kuò)散來(lái)平衡讀寫(xiě)壓力。

          下圖為一條消息從發(fā)送到接收的過(guò)程以及服務(wù)端和客戶(hù)端的執(zhí)行流程:

          如上圖所示:假設(shè)Ua給Ub發(fā)送一條消息,消息寫(xiě)擴(kuò)散至Ua和Ub的各自的域環(huán)中:

          • 1)當(dāng)客戶(hù)端online時(shí),接收到推送的消息位點(diǎn)=當(dāng)前端上域版本+1,本地消息數(shù)據(jù)庫(kù)merge即可;
          • 2)當(dāng)客戶(hù)端offline時(shí),僅進(jìn)行離線(xiàn)推送通知,當(dāng)用戶(hù)重新上線(xiàn)時(shí),進(jìn)行數(shù)據(jù)同步,由服務(wù)端判斷觸發(fā)增量同步還是全量同步。

          針對(duì)第2)點(diǎn),具體邏輯是:

          • 1)如果域環(huán)版本差值小于閥值,增量同步后,進(jìn)行本地消息數(shù)據(jù)庫(kù)merge;
          • 2)當(dāng)域環(huán)版本差值大于閥值,進(jìn)行全量消息拉取,做端上數(shù)據(jù)重建。

          整個(gè)同步邏輯基于閑魚(yú)的即時(shí)消息域環(huán),域環(huán)可以看作是有著固定容量的用戶(hù)消息收件箱,給一個(gè)用戶(hù)發(fā)送的所有消息都會(huì)同步到他的域環(huán)中。

          具體就是:

          • 1)域環(huán)存儲(chǔ):域環(huán)需要支持高并發(fā)數(shù)據(jù)讀寫(xiě),使用阿里分布式KV存儲(chǔ)系統(tǒng)tair來(lái)實(shí)現(xiàn);
          • 2)域環(huán)容量:為減少全量消息同步,以用戶(hù)下次進(jìn)入閑魚(yú)需要同步的平均消息量來(lái)規(guī)劃個(gè)人域環(huán)容量。同時(shí)利用FIFO循環(huán)覆蓋歷史數(shù)據(jù);
          • 3)域環(huán)版本:用戶(hù)當(dāng)前消息位點(diǎn),在消息進(jìn)入個(gè)人域環(huán)時(shí)通過(guò)tair的counter實(shí)現(xiàn)域環(huán)版本嚴(yán)格連續(xù)遞增,用于全量、增量同步判斷。

          上述建設(shè)完成后,閑魚(yú)具備了自己獨(dú)立的即時(shí)消息系統(tǒng),當(dāng)下遇到的問(wèn)題得到了緩解,用戶(hù)體驗(yàn)度有大幅提升。

          5、3.0版:隨著業(yè)務(wù)快速發(fā)展,系統(tǒng)穩(wěn)定性需得到保障

          5.1 技術(shù)背景

          隨著閑魚(yú)業(yè)務(wù)生態(tài)的豐富,IM會(huì)話(huà)與消息內(nèi)容類(lèi)型不斷擴(kuò)展,同時(shí)在用戶(hù)量的快速增長(zhǎng)下,用戶(hù)反饋消息收不到、消息延遲等輿情問(wèn)題日漸突出。

          5.2 問(wèn)題分析

          問(wèn)題1:閑魚(yú)app進(jìn)程無(wú)有效保活機(jī)制,app退到后臺(tái)后進(jìn)程很快就會(huì)被系統(tǒng)掛起,導(dǎo)致長(zhǎng)連接中斷。此時(shí)消息推送走廠商通道,而廠商通道的實(shí)時(shí)性較差,且對(duì)消息推送的優(yōu)先級(jí)設(shè)定有差異,從而造成用戶(hù)感知消息延遲。

          問(wèn)題2:accs在線(xiàn)消息推送時(shí),平均延時(shí)較短,但存在假連情況。而且目前的消息推送鏈路無(wú)ack機(jī)制,造成服務(wù)端以為消息發(fā)出去了但實(shí)際上客戶(hù)端并沒(méi)有收到,用戶(hù)下次打開(kāi)app后才能看到消息,用戶(hù)感知消息延遲。

          PS:造成假連接的原因主要是用戶(hù)退到后臺(tái),accs長(zhǎng)連中斷,但是設(shè)備狀態(tài)更新有延時(shí)。

          問(wèn)題3:目前消息同步的推模式(accs push)、拉模式(mtop),客戶(hù)端未做隔離,異步進(jìn)行處理,導(dǎo)致在某些極端情況下消息數(shù)據(jù)庫(kù)處理異常,引發(fā)消息丟失。

          如:某用戶(hù)上線(xiàn)后連續(xù)收到多條消息,其中一條觸發(fā)域黑洞,在進(jìn)行消息同步端上數(shù)據(jù)重建時(shí),小概率處理出錯(cuò)。

          問(wèn)題4:大部分線(xiàn)上消息問(wèn)題發(fā)現(xiàn)靠輿情反饋,如消息錯(cuò)亂,出問(wèn)題后系統(tǒng)無(wú)感知、無(wú)補(bǔ)救措施且排查困難,僅能跟隨版本做修復(fù)。

          問(wèn)題5:業(yè)務(wù)不斷豐富,孵化出基于消息系統(tǒng)的服務(wù)號(hào)及小程序內(nèi)容營(yíng)銷(xiāo)、消息群組等,各類(lèi)消息發(fā)送鏈路共用域環(huán)與數(shù)據(jù)存儲(chǔ),造成穩(wěn)定性問(wèn)題。

          如:個(gè)人域環(huán)的消息包括IM聊天和營(yíng)銷(xiāo)消息,IM聊天由用戶(hù)觸發(fā),需要保證強(qiáng)到達(dá);而營(yíng)銷(xiāo)消息一般是由系統(tǒng)通過(guò)班車(chē)等方式批量發(fā)送,消息量級(jí)大,tps高,影響IM服務(wù)穩(wěn)定性。

          5.3 解案決方案

          基于上述分析,我們逐個(gè)問(wèn)題進(jìn)行專(zhuān)項(xiàng)解決。

          1)消息重發(fā)與推拉隔離:

          如上圖所示:

          • a. ACK:保障消息及時(shí)到達(dá)。服務(wù)端下行accs消息時(shí),將消息加入重試隊(duì)列并延遲重試,客戶(hù)端在收到accs消息并處理成功后,給服務(wù)端回一個(gè)ack,服務(wù)端收到ack后更新消息到達(dá)狀態(tài),并終止重試,以此避免設(shè)備假連或網(wǎng)絡(luò)不穩(wěn)定的情況;
          • b. 重發(fā):根據(jù)延遲重發(fā)策略決定何時(shí)重發(fā)消息,保障消息確定性到達(dá)。自適應(yīng)延遲重發(fā)策略是指新消息先通過(guò)4次固定N秒的短延遲來(lái)探測(cè)設(shè)備的網(wǎng)絡(luò)狀況,然后根據(jù)網(wǎng)絡(luò)狀況來(lái)遞增固定步長(zhǎng)M的延遲策略,這種策略可以保障在最短的時(shí)間內(nèi),使用最少的重發(fā)次數(shù)將消息投遞成功;
          • c. 消息隊(duì)列:端上引入消息隊(duì)列,按順序處理消息,保證消息處理的準(zhǔn)確性。同時(shí)進(jìn)行推拉隔離,保障隊(duì)列有序消費(fèi),解決了復(fù)雜狀況下并發(fā)處理消息數(shù)據(jù)合并出錯(cuò)的問(wèn)題。

          2)數(shù)據(jù)存儲(chǔ)拆分:

          閑魚(yú)每天發(fā)送的即時(shí)消息中有一半以上是營(yíng)銷(xiāo)消息,營(yíng)銷(xiāo)消息的發(fā)送具有明顯的波峰波谷流量,高峰期會(huì)導(dǎo)致消息數(shù)據(jù)庫(kù)抖動(dòng),影響IM消息。我來(lái)對(duì)消息、摘要、域環(huán)存儲(chǔ)做業(yè)務(wù)隔離,以適應(yīng)不同業(yè)務(wù)場(chǎng)景對(duì)穩(wěn)定性不同的要求。

          具體做法是:

          • 1)IM消息需要極高的穩(wěn)定性保證,其消息及摘要繼續(xù)使用mysql存儲(chǔ);
          • 2)營(yíng)銷(xiāo)消息存儲(chǔ)周期短,穩(wěn)定性要求低于IM,采用Lindorm存儲(chǔ);
          • 3)域環(huán)做實(shí)例級(jí)別隔離,保證IM域環(huán)的容量不會(huì)被其他消息占用,從而影響到消息同步。

          PS:Lindorm是一種多模型的云原生數(shù)據(jù)庫(kù)服務(wù),具有成本低、自定義TTL、容量橫向擴(kuò)展等優(yōu)勢(shì)。

          3)線(xiàn)上問(wèn)題發(fā)現(xiàn)與恢復(fù):

          保障穩(wěn)定性的關(guān)鍵要素是做好各種核心指標(biāo)的監(jiān)控,而監(jiān)控首先要有數(shù)據(jù)來(lái)源,對(duì)服務(wù)端+客戶(hù)端的關(guān)鍵鏈路節(jié)點(diǎn)埋點(diǎn),基于集團(tuán)UT、SLS,通過(guò)blink進(jìn)行實(shí)時(shí)清洗、計(jì)算,最終形成統(tǒng)一規(guī)范的日志數(shù)據(jù)落至SLS,以供實(shí)時(shí)監(jiān)控及鏈路排查。

          消息系統(tǒng)的核心目標(biāo)是保障用戶(hù)消息發(fā)的出、收得到且及時(shí)收到,所以我們通過(guò)計(jì)算發(fā)送成功率、到達(dá)率、消息延遲來(lái)監(jiān)控系統(tǒng)的穩(wěn)定性。

          此外,為了解決用戶(hù)輿情排查困難的問(wèn)題:

          • 1)我們?cè)O(shè)計(jì)了一套指令集,通過(guò)約定指令協(xié)議,服務(wù)端向指定用戶(hù)下發(fā)指令,客戶(hù)端執(zhí)行對(duì)應(yīng)指令進(jìn)行異常數(shù)據(jù)上報(bào),提高排查效率;
          • 2)擴(kuò)展了強(qiáng)制全量同步、數(shù)據(jù)校正等指令,定向修復(fù)用戶(hù)消息數(shù)據(jù)問(wèn)題,相較以往出現(xiàn)嚴(yán)重bug只能讓用戶(hù)卸載重裝解決,這種方式顯然對(duì)用戶(hù)是更友好的。

          經(jīng)過(guò)一系列專(zhuān)項(xiàng)治理,技術(shù)類(lèi)輿情下降50%,從0到1建設(shè)了消息穩(wěn)定性體系,用戶(hù)體驗(yàn)進(jìn)一步提升。

          6、展望未來(lái)

          閑魚(yú)作為電商交易APP, 其中IM是交易的前置鏈路,IM的產(chǎn)品體驗(yàn)極大影響用戶(hù)交易效率。

          前段時(shí)間進(jìn)行用戶(hù)調(diào)研,從閑魚(yú)IM的NPS低于預(yù)期(NPS是用戶(hù)忠誠(chéng)度衡量指標(biāo) = 推薦者%-貶損者%)。

          從用戶(hù)反饋來(lái)看:

          • 1)部分用戶(hù)對(duì)產(chǎn)品功能有較強(qiáng)烈的訴求,諸如消息搜索、分組等;
          • 2)大部分用戶(hù)對(duì)發(fā)送消息過(guò)程中的違規(guī)問(wèn)題難以理解;
          • 3)仍有較多輿情反饋消息收不到或延遲。

          映射到目前閑魚(yú)的即時(shí)消息系統(tǒng)上,我們的系統(tǒng)架構(gòu)依然有很多需要持續(xù)改進(jìn)的地方。

          典型的如:同步協(xié)議冗余,在需求迭代過(guò)程中容易引發(fā)問(wèn)題、有效保活機(jī)制的缺失對(duì)消息即時(shí)送達(dá)的影響、小眾機(jī)型離線(xiàn)消息收不到、多年的數(shù)據(jù)積累在線(xiàn)庫(kù)臃腫等問(wèn)題,影響著閑魚(yú)業(yè)務(wù)迭代速度與NPS。

          作為技術(shù)團(tuán)隊(duì),下一步將提升NPS作為核心技術(shù)目標(biāo),閑魚(yú)的即時(shí)消息系統(tǒng)4.0版架構(gòu)正在路上 ......

          附錄:更多相關(guān)文章

          [1] 更多阿里巴巴的技術(shù)資源:

          阿里釘釘技術(shù)分享:企業(yè)級(jí)IM王者——釘釘在后端架構(gòu)上的過(guò)人之處

          現(xiàn)代IM系統(tǒng)中聊天消息的同步和存儲(chǔ)方案探討

          阿里技術(shù)分享:深度揭秘阿里數(shù)據(jù)庫(kù)技術(shù)方案的10年變遷史

          阿里技術(shù)分享:阿里自研金融級(jí)數(shù)據(jù)庫(kù)OceanBase的艱辛成長(zhǎng)之路

          來(lái)自阿里OpenIM:打造安全可靠即時(shí)通訊服務(wù)的技術(shù)實(shí)踐分享

          釘釘——基于IM技術(shù)的新一代企業(yè)OA平臺(tái)的技術(shù)挑戰(zhàn)(視頻+PPT) [附件下載]

          阿里技術(shù)結(jié)晶:《阿里巴巴Java開(kāi)發(fā)手冊(cè)(規(guī)約)-華山版》[附件下載]

          重磅發(fā)布:《阿里巴巴Android開(kāi)發(fā)手冊(cè)(規(guī)約)》[附件下載]

          作者談《阿里巴巴Java開(kāi)發(fā)手冊(cè)(規(guī)約)》背后的故事

          《阿里巴巴Android開(kāi)發(fā)手冊(cè)(規(guī)約)》背后的故事

          干了這碗雞湯:從理發(fā)店小弟到阿里P10技術(shù)大牛

          揭秘阿里、騰訊、華為、百度的職級(jí)和薪酬體系

          淘寶技術(shù)分享:手淘?xún)|級(jí)移動(dòng)端接入層網(wǎng)關(guān)的技術(shù)演進(jìn)之路

          難得干貨,揭秘支付寶的2維碼掃碼技術(shù)優(yōu)化實(shí)踐之路

          淘寶直播技術(shù)干貨:高清、低延時(shí)的實(shí)時(shí)視頻直播技術(shù)解密

          阿里技術(shù)分享:電商IM消息平臺(tái),在群聊、直播場(chǎng)景下的技術(shù)實(shí)踐

          阿里技術(shù)分享:閑魚(yú)IM基于Flutter的移動(dòng)端跨端改造實(shí)踐

          阿里IM技術(shù)分享(三):閑魚(yú)億級(jí)IM消息系統(tǒng)的架構(gòu)演進(jìn)之路

           

          [2] 有關(guān)IM架構(gòu)設(shè)計(jì)的文章:

          淺談IM系統(tǒng)的架構(gòu)設(shè)計(jì)

          簡(jiǎn)述移動(dòng)端IM開(kāi)發(fā)的那些坑:架構(gòu)設(shè)計(jì)、通信協(xié)議和客戶(hù)端

          一套海量在線(xiàn)用戶(hù)的移動(dòng)端IM架構(gòu)設(shè)計(jì)實(shí)踐分享(含詳細(xì)圖文)

          一套原創(chuàng)分布式即時(shí)通訊(IM)系統(tǒng)理論架構(gòu)方案

          從零到卓越:京東客服即時(shí)通訊系統(tǒng)的技術(shù)架構(gòu)演進(jìn)歷程

          蘑菇街即時(shí)通訊/IM服務(wù)器開(kāi)發(fā)之架構(gòu)選擇

          騰訊QQ1.4億在線(xiàn)用戶(hù)的技術(shù)挑戰(zhàn)和架構(gòu)演進(jìn)之路PPT

          微信后臺(tái)基于時(shí)間序的海量數(shù)據(jù)冷熱分級(jí)架構(gòu)設(shè)計(jì)實(shí)踐

          微信技術(shù)總監(jiān)談架構(gòu):微信之道——大道至簡(jiǎn)(演講全文)

          如何解讀《微信技術(shù)總監(jiān)談架構(gòu):微信之道——大道至簡(jiǎn)》

          快速裂變:見(jiàn)證微信強(qiáng)大后臺(tái)架構(gòu)從0到1的演進(jìn)歷程(一)

          移動(dòng)端IM中大規(guī)模群消息的推送如何保證效率、實(shí)時(shí)性?

          現(xiàn)代IM系統(tǒng)中聊天消息的同步和存儲(chǔ)方案探討

          微信朋友圈千億訪(fǎng)問(wèn)量背后的技術(shù)挑戰(zhàn)和實(shí)踐總結(jié)

          子彈短信光鮮的背后:網(wǎng)易云信首席架構(gòu)師分享億級(jí)IM平臺(tái)的技術(shù)實(shí)踐

          微信技術(shù)分享:微信的海量IM聊天消息序列號(hào)生成實(shí)踐(算法原理篇)

          一套高可用、易伸縮、高并發(fā)的IM群聊、單聊架構(gòu)方案設(shè)計(jì)實(shí)踐

          社交軟件紅包技術(shù)解密(一):全面解密QQ紅包技術(shù)方案——架構(gòu)、技術(shù)實(shí)現(xiàn)等

          從游擊隊(duì)到正規(guī)軍(一):馬蜂窩旅游網(wǎng)的IM系統(tǒng)架構(gòu)演進(jìn)之路

          從游擊隊(duì)到正規(guī)軍(二):馬蜂窩旅游網(wǎng)的IM客戶(hù)端架構(gòu)演進(jìn)和實(shí)踐總結(jié)

          從游擊隊(duì)到正規(guī)軍(三):基于Go的馬蜂窩旅游網(wǎng)分布式IM系統(tǒng)技術(shù)實(shí)踐

          瓜子IM智能客服系統(tǒng)的數(shù)據(jù)架構(gòu)設(shè)計(jì)(整理自現(xiàn)場(chǎng)演講,有配套PPT)

          IM開(kāi)發(fā)基礎(chǔ)知識(shí)補(bǔ)課(九):想開(kāi)發(fā)IM集群?先搞懂什么是RPC!

          阿里技術(shù)分享:電商IM消息平臺(tái),在群聊、直播場(chǎng)景下的技術(shù)實(shí)踐

          一套億級(jí)用戶(hù)的IM架構(gòu)技術(shù)干貨(上篇):整體架構(gòu)、服務(wù)拆分等

          一套億級(jí)用戶(hù)的IM架構(gòu)技術(shù)干貨(下篇):可靠性、有序性、弱網(wǎng)優(yōu)化等

          從新手到專(zhuān)家:如何設(shè)計(jì)一套億級(jí)消息量的分布式IM系統(tǒng)

          企業(yè)微信的IM架構(gòu)設(shè)計(jì)揭秘:消息模型、萬(wàn)人群、已讀回執(zhí)、消息撤回等

          融云技術(shù)分享:全面揭秘億級(jí)IM消息的可靠投遞機(jī)制

          IM開(kāi)發(fā)技術(shù)學(xué)習(xí):揭秘微信朋友圈這種信息推流背后的系統(tǒng)設(shè)計(jì)

          阿里IM技術(shù)分享(三):閑魚(yú)億級(jí)IM消息系統(tǒng)的架構(gòu)演進(jìn)之路

          >> 更多同類(lèi)文章 ……

          本文已同步發(fā)布于“即時(shí)通訊技術(shù)圈”公眾號(hào)。

          同步發(fā)布鏈接是:http://www.52im.net/thread-3699-1-1.html 

          posted @ 2021-09-13 15:12 Jack Jiang 閱讀(330) | 評(píng)論 (0)編輯 收藏

               摘要: 本文引用自“ 豆米博客”的《JS實(shí)時(shí)通信三把斧》系列文章,有優(yōu)化和改動(dòng)。1、引言有關(guān)Web端即時(shí)通訊技術(shù)的文章我已整理過(guò)很多篇,閱讀過(guò)的讀者可能都很熟悉,早期的Web端即時(shí)通訊方案,受限于Web客戶(hù)端的技術(shù)限制,想實(shí)現(xiàn)真正的“即時(shí)”通信,難度相當(dāng)大。傳統(tǒng)的Web端即時(shí)通訊技術(shù)從短輪詢(xún)到長(zhǎng)連詢(xún),再到Comet技術(shù),在如此原始的HTML標(biāo)準(zhǔn)之下,為了實(shí)現(xiàn)...  閱讀全文

          posted @ 2021-09-07 10:47 Jack Jiang 閱讀(193) | 評(píng)論 (0)編輯 收藏

          本文由融云技術(shù)團(tuán)隊(duì)原創(chuàng)分享,原題“技術(shù)實(shí)踐丨萬(wàn)人群聊的消息分發(fā)控速方案”,為使文章更好理解,內(nèi)容有修訂。

          1、引言

          傳統(tǒng)意義上的IM群聊,通常都是像微信這樣的500人群,或者QQ的2000人群(QQ有3000人群,但那是單獨(dú)收費(fèi)的,也就意味著它并非無(wú)門(mén)檻標(biāo)配,能用上的人并不多)。

          自從國(guó)外某號(hào)稱(chēng)“世界上最安全的IM”搞出萬(wàn)人群聊之后,萬(wàn)人群迅速被國(guó)內(nèi)的使用者們接受。伴隨著移動(dòng)互聯(lián)網(wǎng)的發(fā)展,即時(shí)通訊服務(wù)被廣泛應(yīng)用于各個(gè)行業(yè)(以經(jīng)不再局限于傳統(tǒng)IM社交應(yīng)用領(lǐng)域),隨著業(yè)務(wù)快速發(fā)展,傳統(tǒng)百人、千人上限的群聊已經(jīng)無(wú)法滿(mǎn)足很多業(yè)務(wù)場(chǎng)景需求,所以萬(wàn)人甚至十萬(wàn)人的超大群也算是相伴而生、順應(yīng)潮流。 

          ▲ “紙飛機(jī)”的萬(wàn)人群(開(kāi)發(fā)人員顫抖中...)

          IM群聊一直是IM應(yīng)用中比較有難度的熱點(diǎn)技術(shù)之一,通常意義的群聊,無(wú)非就是500人群、1000人群、2000人群這樣,技術(shù)實(shí)現(xiàn)上比單聊要復(fù)雜不少。然而對(duì)于萬(wàn)人群聊(甚至十萬(wàn)人群聊)來(lái)說(shuō),相比百人、千人群聊,技術(shù)實(shí)現(xiàn)上那幾乎是另一個(gè)技術(shù)維度的事情,難度要高很多。

          本文根據(jù)融云技術(shù)團(tuán)隊(duì)的實(shí)踐經(jīng)驗(yàn),總結(jié)了萬(wàn)人群聊消息投遞方案的一些思考和實(shí)踐,希望能給你帶來(lái)啟發(fā)。

          學(xué)習(xí)交流:

          - 即時(shí)通訊/推送技術(shù)開(kāi)發(fā)交流5群:215477170 [推薦]

          - 移動(dòng)端IM開(kāi)發(fā)入門(mén)文章:《新手入門(mén)一篇就夠:從零開(kāi)發(fā)移動(dòng)端IM

          - 開(kāi)源IM框架源碼:https://github.com/JackJiang2011/MobileIMSDK

          (本文同步發(fā)布于:http://www.52im.net/thread-3687-1-1.html

          2、相關(guān)文章

          萬(wàn)人群聊有關(guān)的技術(shù)文章還可讀一讀以下這篇:

          1. 網(wǎng)易云信技術(shù)分享:IM中的萬(wàn)人群聊技術(shù)方案實(shí)踐總結(jié)
          2. 企業(yè)微信的IM架構(gòu)設(shè)計(jì)揭秘:消息模型、萬(wàn)人群、已讀回執(zhí)、消息撤回等
          3. 阿里釘釘技術(shù)分享:企業(yè)級(jí)IM王者——釘釘在后端架構(gòu)上的過(guò)人之處

          融云技術(shù)團(tuán)隊(duì)分享的其它文章:

          1. 融云技術(shù)分享:融云安卓端IM產(chǎn)品的網(wǎng)絡(luò)鏈路保活技術(shù)實(shí)踐
          2. 融云技術(shù)分享:全面揭秘億級(jí)IM消息的可靠投遞機(jī)制
          3. 融云技術(shù)分享:基于WebRTC的實(shí)時(shí)音視頻首幀顯示時(shí)間優(yōu)化實(shí)踐
          4. IM消息ID技術(shù)專(zhuān)題(三):解密融云IM產(chǎn)品的聊天消息ID生成策略

          3、超大群面臨的技術(shù)挑戰(zhàn)

          與百人群、千人群相比,萬(wàn)人、甚至十萬(wàn)人超大群,大幅提升了群的觸達(dá)人數(shù),對(duì)于很多業(yè)務(wù)場(chǎng)景來(lái)說(shuō),好處不言而喻。

          然而單群成員如此之大,給 IM 系統(tǒng)的流量沖擊非常巨大,技術(shù)難度可想而之。我們先來(lái)分析一下超大群的技術(shù)挑戰(zhàn)。

          以一個(gè)萬(wàn)人群的模型為例:

          • 1)如果群中有人發(fā)了消息,那么這條消息需要按照 1:9999 的比例進(jìn)行分發(fā)投遞,如果我們按照常規(guī)消息的處理流程,那么消息處理服務(wù)壓力巨大;
          • 2)消息量大的情況下,服務(wù)端向客戶(hù)端直推消息的處理速度將會(huì)成為系統(tǒng)瓶頸,而一旦用戶(hù)的消息下發(fā)隊(duì)列造成了擠壓,會(huì)影響到正常的消息分發(fā),也會(huì)導(dǎo)致服務(wù)緩存使用量激增;
          • 3)在微服務(wù)架構(gòu)中,服務(wù)以及存儲(chǔ)(DB,緩存)之間的 QPS 和網(wǎng)絡(luò)流量也會(huì)急劇增高;
          • 4)以群為單位的消息緩存,內(nèi)存和存儲(chǔ)開(kāi)銷(xiāo)較大(消息體的存儲(chǔ)被放大了萬(wàn)倍)。

          基于這些技術(shù)挑戰(zhàn),要想真正達(dá)成超大群的技術(shù)目標(biāo),勢(shì)必要做特定的技術(shù)優(yōu)化來(lái)應(yīng)對(duì)。

          4、一般群聊的消息投遞模型

          先來(lái)看看普通群聊的消息投遞模型。

          我們的普通群聊消息投遞模型如下圖所示:

          如上圖所示,當(dāng)用戶(hù)在普通群里發(fā)了一條消息后,投遞路徑是:

          • 1)消息先到群組服務(wù);
          • 2)然后通過(guò)群組服務(wù)緩存的群關(guān)系,鎖定這條消息最終需要分發(fā)的目標(biāo)用戶(hù);
          • 3)再根據(jù)一定的策略分發(fā)到消息服務(wù)上;
          • 4)消息服務(wù)再根據(jù)用戶(hù)的在線(xiàn)狀態(tài)和消息狀態(tài)來(lái)判斷這條消息是直推、通知拉取還是轉(zhuǎn) Push,最終投遞給目標(biāo)用戶(hù)。

          普通群聊的消息投遞,正像您期待的那樣,基本上大家的實(shí)現(xiàn)手段都大差不差。然而對(duì)于萬(wàn)人群來(lái)說(shuō),這顯然還不夠。

          下面來(lái)看看我們針對(duì)萬(wàn)人群聊消息投遞的技術(shù)優(yōu)化手段。

          5、萬(wàn)人群聊消息投遞優(yōu)化手段1:控速

          針對(duì)萬(wàn)人群的消息投遞,我們的一個(gè)主要手段就是控速。

          如上圖所示。

          首先:我們會(huì)根據(jù)服務(wù)器的核數(shù)來(lái)建立多個(gè)群消息分發(fā)隊(duì)列,這些隊(duì)列我們?cè)O(shè)置了不同的休眠時(shí)間以及不同的消費(fèi)線(xiàn)程數(shù)。

          通俗來(lái)講,可以將隊(duì)列這樣劃分為快、中、慢等隊(duì)列。

          其次:我們根據(jù)群成員數(shù)量的大小來(lái)將所有群映射到相應(yīng)的隊(duì)列中。

          規(guī)則是:

          • 1)小群映射到快隊(duì)列中;
          • 2)大群映射到相應(yīng)的慢隊(duì)列中。

          然后:小群由于人數(shù)少,對(duì)服務(wù)的影響很小,所以服務(wù)利用快隊(duì)列快速的將群消息分發(fā)出去,而大群群消息則利用慢隊(duì)列的相對(duì)高延時(shí)來(lái)起到控速的作用。

          6、萬(wàn)人群聊消息投遞優(yōu)化手段2:合并

          在本文第3節(jié)中提到的萬(wàn)人群聊所面臨的技術(shù)挑戰(zhàn),最主要的挑戰(zhàn)其實(shí)就是消息進(jìn)行擴(kuò)散分發(fā)投遞后,消息被克隆出N條,消息流量瞬間被放大。

          舉個(gè)例子:當(dāng)一條群消息發(fā)送到 IM 服務(wù)器后,需要從群組服務(wù)投遞給消息服務(wù),如果每一個(gè)群成員都投遞一次,并且投遞的群消息內(nèi)容是一致的話(huà),那肯定會(huì)造成相應(yīng)的資源浪費(fèi)和服務(wù)壓力。

          那么針對(duì)這種情況,我們的解決方案就是進(jìn)行消息合并投遞。

          原理就是:服務(wù)落點(diǎn)計(jì)算中我們使用的是一致性哈希,群成員落點(diǎn)相對(duì)固定,所以落點(diǎn)一致的群成員我們可以合并成一次請(qǐng)求進(jìn)行投遞,這樣就大幅提高了投遞效率同時(shí)減少了服務(wù)的壓力。

          下圖是云信團(tuán)隊(duì)分享的萬(wàn)人群消息合并投遞邏輯:

          ▲ 上圖引用自《IM中的萬(wàn)人群聊技術(shù)方案實(shí)踐總結(jié)

          如上圖所示,云信團(tuán)隊(duì)的萬(wàn)人群消息合并投遞方案是:按Link分組路由消息,同一Link上的全部群成員只需要路由一條消息即可。

          7、十萬(wàn)、百萬(wàn)級(jí)的超大群處理方案

          在實(shí)際群聊業(yè)務(wù)中,還有一種業(yè)務(wù)場(chǎng)景是超大規(guī)模群,這種群的群人數(shù)達(dá)到了數(shù)十萬(wàn)甚至上百萬(wàn)。

          這種群如果按照上述的投投遞方案,勢(shì)必仍會(huì)造成消息節(jié)點(diǎn)的巨大壓力。

          比如我們有一個(gè)十萬(wàn)人的群,消息節(jié)點(diǎn)五臺(tái),消息服務(wù)處理消息的上限是一秒鐘 4000 條,那每臺(tái)消息節(jié)點(diǎn)大約會(huì)分到 2 萬(wàn)條群消息,這已大大超出了消息節(jié)點(diǎn)的處理能力。

          所以為了避免上述問(wèn)題,我們會(huì)將群成員上線(xiàn)超過(guò)3000的群識(shí)別為萬(wàn)人群、超級(jí)群,這種級(jí)別的群可以根據(jù)服務(wù)器數(shù)量和服務(wù)器配置相應(yīng)做調(diào)整針對(duì)這種超級(jí)群會(huì)用特殊的隊(duì)列來(lái)處理群消息的投遞。

          這個(gè)特殊的隊(duì)列1秒鐘往后端消息服務(wù)投遞的消息數(shù)是消息服務(wù)處理上限的一半(留相應(yīng)的能力處理其他消息),如果單臺(tái)消息服務(wù)處理的 QPS 上限是 4000,那群組服務(wù)一秒往單臺(tái)消息服務(wù)最多投遞 2000 條。

          8、寫(xiě)在最后

          未來(lái),我們也會(huì)針對(duì)群消息進(jìn)行引用投遞,對(duì)于大群里發(fā)的消息體比較大的消息,我們給群成員只分發(fā)和緩存消息的索引,比如 MessageID。等群成員真正拉取群消息時(shí)再?gòu)膶⑾⒔M裝好給客戶(hù)端分發(fā)下去。這樣做會(huì)節(jié)省分發(fā)的流量以及存儲(chǔ)的空間。

          隨著互聯(lián)網(wǎng)的發(fā)展,群組業(yè)務(wù)的模型和壓力也在不停地?cái)U(kuò)展,后續(xù)可能還會(huì)遇到更多的挑戰(zhàn),當(dāng)然也會(huì)不斷迭代出更優(yōu)的處理方式來(lái)應(yīng)對(duì)。

          附錄:更多IM群聊技術(shù)文章

          快速裂變:見(jiàn)證微信強(qiáng)大后臺(tái)架構(gòu)從0到1的演進(jìn)歷程(一)

          如何保證IM實(shí)時(shí)消息的“時(shí)序性”與“一致性”?

          IM單聊和群聊中的在線(xiàn)狀態(tài)同步應(yīng)該用“推”還是“拉”?

          IM群聊消息如此復(fù)雜,如何保證不丟不重?

          微信后臺(tái)團(tuán)隊(duì):微信后臺(tái)異步消息隊(duì)列的優(yōu)化升級(jí)實(shí)踐分享

          移動(dòng)端IM中大規(guī)模群消息的推送如何保證效率、實(shí)時(shí)性?

          現(xiàn)代IM系統(tǒng)中聊天消息的同步和存儲(chǔ)方案探討

          關(guān)于IM即時(shí)通訊群聊消息的亂序問(wèn)題討論

          IM群聊消息的已讀回執(zhí)功能該怎么實(shí)現(xiàn)?

          IM群聊消息究竟是存1份(即擴(kuò)散讀)還是存多份(即擴(kuò)散寫(xiě))?

          一套高可用、易伸縮、高并發(fā)的IM群聊、單聊架構(gòu)方案設(shè)計(jì)實(shí)踐

          [技術(shù)腦洞] 如果把14億中國(guó)人拉到一個(gè)微信群里技術(shù)上能實(shí)現(xiàn)嗎?

          IM群聊機(jī)制,除了循環(huán)去發(fā)消息還有什么方式?如何優(yōu)化?

          網(wǎng)易云信技術(shù)分享:IM中的萬(wàn)人群聊技術(shù)方案實(shí)踐總結(jié)

          阿里釘釘技術(shù)分享:企業(yè)級(jí)IM王者——釘釘在后端架構(gòu)上的過(guò)人之處

          IM群聊消息的已讀未讀功能在存儲(chǔ)空間方面的實(shí)現(xiàn)思路探討

          直播系統(tǒng)聊天技術(shù)(一):百萬(wàn)在線(xiàn)的美拍直播彈幕系統(tǒng)的實(shí)時(shí)推送技術(shù)實(shí)踐之路

          直播系統(tǒng)聊天技術(shù)(二):阿里電商IM消息平臺(tái),在群聊、直播場(chǎng)景下的技術(shù)實(shí)踐

          直播系統(tǒng)聊天技術(shù)(三):微信直播聊天室單房間1500萬(wàn)在線(xiàn)的消息架構(gòu)演進(jìn)之路

          直播系統(tǒng)聊天技術(shù)(四):百度直播的海量用戶(hù)實(shí)時(shí)消息系統(tǒng)架構(gòu)演進(jìn)實(shí)踐

          企業(yè)微信的IM架構(gòu)設(shè)計(jì)揭秘:消息模型、萬(wàn)人群、已讀回執(zhí)、消息撤回等

          融云IM技術(shù)分享:萬(wàn)人群聊消息投遞方案的思考和實(shí)踐

          >> 更多同類(lèi)文章 ……

          本文已同步發(fā)布于“即時(shí)通訊技術(shù)圈”公眾號(hào)。

          同步發(fā)布鏈接是:http://www.52im.net/thread-3687-1-1.html

          posted @ 2021-08-30 11:34 Jack Jiang 閱讀(213) | 評(píng)論 (0)編輯 收藏

          僅列出標(biāo)題
          共51頁(yè): First 上一頁(yè) 22 23 24 25 26 27 28 29 30 下一頁(yè) Last 
          Jack Jiang的 Mail: jb2011@163.com, 聯(lián)系QQ: 413980957, 微信: hellojackjiang
          主站蜘蛛池模板: 百色市| 武穴市| 靖江市| 喀什市| 阿拉善盟| 蚌埠市| 承德市| 山东| 江永县| 亚东县| 赤城县| 湖北省| 辉南县| 岑溪市| 西和县| 体育| 容城县| 辽阳县| 罗山县| 集安市| 昌黎县| 红桥区| 南开区| 彰化市| 琼结县| 于都县| 瓦房店市| 巴青县| 中方县| 迁西县| 鄢陵县| 永嘉县| 仁寿县| 淮安市| 白玉县| 和田县| 磴口县| 沙雅县| 澜沧| 嘉荫县| 莱阳市|