<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Jack Jiang

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

    1、點(diǎn)評

    IM聊天消息的可靠投遞,是每個線上產(chǎn)品都要考慮的IM熱點(diǎn)技術(shù)問題。

    IM聊天消息能保證可靠送達(dá),對于用戶來說,就好比把錢存在銀行不怕被偷一樣,是信任的問題。試想,如果用戶能明顯感知到聊天消息無法保證送達(dá),誰還愿意來用你的APP?誰也不希望自已的話就像浮云一樣隨風(fēng)飄逝。

    必竟用IM聊天,雖然很多時候是費(fèi)話,但總有關(guān)鍵時刻存在——比如向女神表白(哪怕明知被拒),作為合格的舔狗一定不希望女神錯過這條消息。

    所以,消息的可靠投遞是每款I(lǐng)M產(chǎn)品和立足之本,也是IM開發(fā)者們孜孜不倦追求的技術(shù)目標(biāo)。

    本文作者將以自已IM開發(fā)過程中的真實(shí)總結(jié),分享針對大量離線聊天消息,在確保用戶端體驗(yàn)不降級的前提下,保證離線消息的可靠投遞。

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

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

    - 移動端IM開發(fā)入門文章:《新手入門一篇就夠:從零開發(fā)移動端IM

    本文已同步發(fā)布于“即時通訊技術(shù)圈”公眾號,歡迎關(guān)注:

    ▲ 本文在公眾號上的鏈接是:https://mp.weixin.qq.com/s/T2w9h_AN_T2UnqNdVikX0Q,原文鏈接是:http://www.52im.net/thread-3069-1-1.html

     

    2、本文作者 

    fzully(柳林勇):2005年數(shù)學(xué)系畢業(yè),先后就職于福建新大陸、福建富士通、北京世紀(jì)奧通。長期從事服務(wù)端軟件開發(fā),涉及SIP服務(wù)器、內(nèi)核RTP轉(zhuǎn)送、電信級AAA認(rèn)證系統(tǒng)、IM即時通訊系統(tǒng)等。在分布式高性能系統(tǒng)設(shè)計(jì)有多年經(jīng)驗(yàn)積累。

    本作者的另一篇:《IM群聊消息的已讀未讀功能在存儲空間方面的實(shí)現(xiàn)思路探討》也已被即時通訊網(wǎng)收錄并整理發(fā)布,有興趣可以前往閱讀。

    3、相關(guān)文章

    從客戶端的角度來談?wù)勔苿佣薎M的消息可靠性和送達(dá)機(jī)制

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

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

    IM消息送達(dá)保證機(jī)制實(shí)現(xiàn)(二):保證離線消息的可靠投遞》(* 強(qiáng)烈推薦

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

    一個低成本確保IM消息時序的方法探討

    IM群聊消息如此復(fù)雜,如何保證不丟不重?》(* 強(qiáng)烈推薦

    移動端IM登錄時拉取數(shù)據(jù)如何作到省流量?》(* 強(qiáng)烈推薦

    完全自已開發(fā)的IM該如何設(shè)計(jì)“失敗重試”機(jī)制?

    IM開發(fā)干貨分享:我是如何解決大量離線消息導(dǎo)致客戶端卡頓的》(* 強(qiáng)烈推薦

    4、正文引言

    暗戀女神良久,終于鼓起勇氣決定向女神寫一封情書。但如何表達(dá)才能感動女神?自感才疏學(xué)淺,于是通讀四書五經(jīng)、熟背唐詩宋詞、遍覽四大名著,已然腹有詩書氣自華。一周末冥思苦想整日才寫就一首七言律詩,雖無驚天地泣鬼神之勢,但誠摯的愛念在字里行間里流淌,亦歌亦詩,相信會感動到女神,手機(jī)欣然發(fā)出。

    發(fā)出一秒后,手心冒汗,感覺臉頰發(fā)燙,心臟像受驚嚇的野兔一樣快速跳動,就像第一次看見女神那時的感覺。閉著眼睛,想象女神看到消息時的情形,她是否也期盼我的表白?看到消息時是否心跳加速、小臉緋紅?

    一分鐘后,緊盯手機(jī)屏幕,等待、期盼女神回復(fù)。

    時間一分一秒地逝去,等一分鐘像等一年一樣漫長。

    一小時后,仍然杳無音訊,難道她沒看到消息么?或許在忙什么而沒留意手機(jī)吧!

    一天過去了,坐立不安,等待是一種痛苦的煎熬,期待和煎熬在心中交織翻滾,有幾個瞬間甚至希望女神趕快拒絕自己,好讓自己解脫!茶飯無味,失眠多天,整日魂不守舍。

    一個月過去了,死心。

    半年后,女神出嫁,婚禮那天前去祝福。席間亦隨眾觥籌交錯,略有醉意,向女神敬酒:祝福你,但愿以后能遇見像你這樣的女人。女神先是愣住、收起笑容,低下頭,目光無神地看著大紅地毯,長嘆一聲,言:我等你表白,等了一年!空氣凝滯了幾秒,女神強(qiáng)作歡顏:從今往后,各自安好吧,干杯!

    我轉(zhuǎn)身踱回到座位,拿起手機(jī),打開那個App,看著曾經(jīng)發(fā)出的情書,一切仿佛還在昨日,但故事腳本已被別人書寫,欲哭無淚,嘆老天為何如此捉弄我?為何我發(fā)的消息女神沒收到啊!

    失魂落魄地回到家里,從冰箱里拿出幾瓶羅斯福10號來麻醉自己,在酒精強(qiáng)烈的作用下,迷迷入睡。

    第二天醒來,我明白了一個道理:對IM系統(tǒng)而言,消息必達(dá)永遠(yuǎn)擺在第一位!

    以上是胡說八道,以下開始正文。。。

    5、用全量離線消息實(shí)現(xiàn)消息必達(dá)

    我們在重構(gòu)IM系統(tǒng)時,需解決上一代設(shè)計(jì)的痛點(diǎn)之一就是確保消息必達(dá)。

    5.1 離線消息實(shí)現(xiàn)消息必達(dá)的流程

    自然而然地會想到這么做——即由服務(wù)端為每個人保存一個“離線消息列表”。

    具體的思路是這樣:

    • 1)當(dāng)用戶在線時,由IMS主動確保消息下發(fā)且收到客戶端的應(yīng)答確認(rèn)時,才認(rèn)為消息送達(dá)客戶端,相應(yīng)地把消息從“離線消息列表”移除;
    • 2)如果客戶端沒有發(fā)回應(yīng)答確認(rèn),IM服務(wù)端會再發(fā)送。

    以此來確保消息一定送到客戶端,看起來是很符合邏輯。當(dāng)時調(diào)查過市面上多款I(lǐng)M,行為基本如此。

    5.2 海嘯般的離線消息

    5.2.1)和平時期:

    重構(gòu)后的IM上線,內(nèi)部測試及在公網(wǎng)運(yùn)行,離線消息的工作一直很正常。

    5.2.2)被簽到簽死了:

    后來,為某客戶部署的私有環(huán)境,其用戶量達(dá)幾十萬,其中的一個組織接近三萬人,全員群也接近三萬人;還有,底下的部門也有相應(yīng)的群組,幾百到幾千人群不等。

    “報到”、“簽到”。。。大量的類似消息被發(fā)到幾千、幾萬人的群內(nèi),然后如果有人一兩天沒上線,或者被加入到多個組織內(nèi),等到其上線時,幾萬條離線消息像海嘯一般涌來,您想象一下:手機(jī)用戶剛登陸的幾分鐘內(nèi),是什么場景?

    用戶真的很無辜:我不就是登陸了一下App,叮叮咚咚響了幾分鐘,還卡,還發(fā)熱。。。

    客戶端承受不起大規(guī)模離線消息的轟炸,怎么辦?

    5.3 臨時運(yùn)用方案

    • 1)對若干大組織的全員群,對非管理員禁言;
    • 2)通知所有用戶不要在大群簽到。

    我承認(rèn),這確實(shí)不算是個正經(jīng)方案。。。

    6、遠(yuǎn)離全量離線消息

    我承認(rèn),一開始設(shè)計(jì)離線消息時,真沒想到是這樣的使用場景。對于大多數(shù)IM的開發(fā)者,或許不會碰到這種場景(但凡事住最壞的可能性想,總是沒錯的)。

    6.1 放棄以離線消息的形式實(shí)現(xiàn)消息必達(dá)

    我開始思考什么是消息必達(dá),以前的想法是:把用戶該收的消息都送到其客戶端,是消息必達(dá)。

    后來,給消息必達(dá)下了新的定義:

    • 1)用戶有新消息時,確保讓用戶知道;
    • 2)當(dāng)用戶要查看這些消息時,確保其可一條不漏地看到。

    打個比方:

    • 1)客戶要把錢給您,不必送到您家里才算送到;
    • 2)而是轉(zhuǎn)賬到您的銀行賬戶上,并告知您;
    • 3)當(dāng)您要用錢時,直接從銀行賬戶上消費(fèi)即可。

    從此,不會在用戶上線時向其發(fā)送大量離線消息(即全量推送)。

    6.2 以會話列表為基礎(chǔ)來實(shí)現(xiàn)消息必達(dá)

    客戶端在上線時,先從服務(wù)端更新會話列表,也就是你通常在每個IM客戶端的首頁看到的這個(如下圖所示)。

    上圖引用自《IM開發(fā)快速入門(一):什么是IM系統(tǒng)?

    每一個會話列表項(xiàng)包含如下信息(此處簡化了與本文無關(guān)的成員變量):

    {

            // 會話對象的角色類型,比如私聊、群聊、系統(tǒng)通知、業(yè)務(wù)通知。。。

            uint32  session_role;

            // 會話對象的ID

            uint32        session_id;

            // 會話時間戳,用于消息同步;

            // 指會話的最后操作時間,比如清除角標(biāo)的時間,與會話最后一條的消息時間未必一致

            uint64 session_timestamp;

            // true表示新增或更新,false表示被刪除

            boolis_add;

     

            // 當(dāng)is_add=false時,忽略以下信息

     

            // 僅用于顯示角標(biāo)的未讀數(shù)量,當(dāng)用戶查看該會話后清零,且客戶端多端同步

            uint32 new_msg_count;

            // 會話的最后一條消息

            MessageItem         latest_msg;

            // 跳轉(zhuǎn)消息的時間戳,即new_msg_count的最舊1條消息的時間

            uint64 goto_timestamp;

    }

    為方便討論,假設(shè)以下前提:

    • 1)周五傍晚18:00下班,我關(guān)閉App,我是9527;
    • 2)有1小姐姐向我發(fā)了5條消息留言,約我周末去海邊玩,她是楊冪3306;
    • 3)然后,另1小姐姐也向我發(fā)了33條消息留言,內(nèi)容我不便透露,她是景甜5672;
    • 4)嚴(yán)正聲明:我跟她們很清白,其實(shí)我喜歡的是6379。

    對,既然是假設(shè),假一點(diǎn)也無妨。

    我下班回到家,看到手機(jī)有通知欄消息,打開App將會發(fā)生哪些事呢?

    App和IM后端的交互:

    1)登錄后,App以18:00填充參數(shù)latest_session_time,向IMS獲取會話列表(其實(shí)不是以下線時間18:00,但這樣更易理解);

    2)IM后端檢查發(fā)現(xiàn)我從18:00開始,有2個會話更新了,于是向App發(fā)送應(yīng)答,以增量形式攜帶2個會話項(xiàng):楊冪3306,景甜5672。其中景甜5672的會話項(xiàng)信息如下:

    {

            uint32  session_role = Role_User; //表示私聊

            uint32        session_id = 5672; //景甜的ID

            uint64  session_timestamp = 1594464295335672; //最后一條消息的時間戳,微秒

            boolis_add = true; // true表示是更新項(xiàng)

            uint32  new_msg_count = 33; // 景甜向我發(fā)了33條消息

            MessageItem         latest_msg = "房號是0520"; //最后1條消息,結(jié)構(gòu)體MessageItem簡略不表

            uint64  goto_timestamp = 1594463697556677; // 向我發(fā)的33條消息的最早1條的時間

    }

    3)App收到步驟2的應(yīng)答,我在App的會話列表窗口里,能看到2項(xiàng)更新,景甜發(fā)來的未讀消息數(shù)33條,楊冪的是5條,如下圖所示:

     

    4)點(diǎn)開景甜5672的會話,App將向IMS發(fā)起同步消息的請求,獲取最新的10條聊天消息(為了顯示一屏):

    {

            uint32  session_role = Role_User; //表示私聊

            uint32        session_id = 5672; //景甜的ID

            uint64        begin_time  = 1594464295335672; //步驟2返回的session_timestamp

            uint64        end_time  = 1594434153444222; //景甜上午向我發(fā)的最后一條消息的時間

            uint32        max_pieces = 10; //本次最多取10條,PC屏幕大則不妨取20條

    }

    5)IM后端收到步驟4請求,將返回33條新消息的最后10條給App,呈現(xiàn)聊天窗口內(nèi),且聊天窗口上方有一個tip:“↑ 33條新消息”,如下圖所示:

     
     

    6)我可以向上翻動聊天記錄,那么App將持續(xù)向IMS獲取第2批同步消息;或者也可以點(diǎn)擊tip:“↑ 33條新消息”,直接跳轉(zhuǎn)到33條消息的最舊一條,這樣支持從最舊的消息向新的翻看。

    相比于客戶端簡單地被動接收服務(wù)端的離線通知方式,這種設(shè)計(jì)使得客戶端的處理邏輯更復(fù)雜。

    主要體現(xiàn)在:

    • 1)客戶端向服務(wù)端取的同步消息是未必完整,這些存在客戶端的消息,在時間區(qū)間上可能不連續(xù)的;
    • 2)客戶端需要知道不同消息之間是否有斷代,如果有則需要向服務(wù)端查詢同步消息來merge本地信息,使其連續(xù),即客戶端要實(shí)現(xiàn)消息融合。

    我的建議:用C++實(shí)現(xiàn)一個統(tǒng)一的底層imsdk庫,來負(fù)責(zé)這些共通的消息處理和存儲。避免各客戶端(Windows,iOS,Android等)各自實(shí)現(xiàn)這些邏輯,減少工作量,也降低各端不一致的風(fēng)險。

    6.3 以會話列表為基礎(chǔ)與用全量離線消息的方案對比

    6.3.1)用全量離線消息實(shí)現(xiàn)的方案優(yōu)缺點(diǎn):

    實(shí)現(xiàn)原理:由IM服務(wù)端確保消息送達(dá)客戶端,客戶端存儲后發(fā)回確認(rèn)。

    方案優(yōu)點(diǎn):邏輯簡單。

    在聊天消息不同數(shù)量級時的表現(xiàn):

    • a. 離線消息量不多(如幾百條):沒有效率問題,且消息全部達(dá)到客戶端本地,方便進(jìn)行查找等動作;
    • b. 離線消息量巨大(如幾萬條):用戶登錄瞬間CS間瞬時流量大,客戶端瞬時要存儲、更新的數(shù)據(jù)量巨大,可能出現(xiàn)卡頓、假死等情況。

    6.3.2)用會話列表為基礎(chǔ)的方案優(yōu)缺點(diǎn):

    實(shí)現(xiàn)原理:客戶端先同步會話列表,由用戶驅(qū)動不定次獲取同步消息。

    方案缺點(diǎn):邏輯復(fù)雜,客戶端增加不少工作。

    在聊天消息不同數(shù)量級時的表現(xiàn):

    • a. 離線消息量不多(如幾百條):沒優(yōu)勢;
    • b. 離線消息量巨大(如幾萬條):登錄時交互數(shù)據(jù)小,對IM后端、客戶端、用戶體驗(yàn),都比較友好。

    7、多終端條件下,如何得到完整消息履歷?

    由于同一個用戶的每個終端,其會話最后更新時間、每個會話的最后一條時間可能都不一樣,參照上一節(jié)的實(shí)現(xiàn)思路,可以得到解決方案。

    具體如下:

    • 1)參照第6.2章節(jié)的“App和IM后端的交互”第1個步驟,可取到不同的增量變化的會話列表項(xiàng);
    • 2)參照第6.2章節(jié)的“App和IM后端的交互”第4個步驟,可取到任一區(qū)間的同步消息,得到完整消息。

    8、離線消息是否就徹底廢棄了?

    有若干情況,仍然需要保留離線消息,以確保消息送達(dá)。

    比如以下情形:

    • 1)別人向我發(fā)送離線文件:這種情況下不能依賴同步消息來獲取。因?yàn)椴灰噪x線消息通知的話,用戶在沒有拉取到對應(yīng)的同步消息前,是不知道有離線文件的;
    • 2)撤回消息:即使接收者不拉取同步,仍然要保證在上線后其數(shù)據(jù)在第一時間被撤回。注意:這里可能存在多端撤回問題;
    • 3)用戶在線時的消息下發(fā):由于用戶在線時,IM后端向客戶端發(fā)送消息可能碰到網(wǎng)絡(luò)抖動等情況,導(dǎo)致消息下發(fā)失敗,這些消息先可以直接存在離線消息隊(duì)列,IM后端可在收到客戶端的心跳包時重發(fā)消息。相當(dāng)于維護(hù)了一個在線消息的離線隊(duì)列。

    9、本文結(jié)語

    曾經(jīng)有一段真摯的愛情擺在我面前,如果時間倒流到半年前,我會選擇一個靠譜的IM來發(fā)送消息,也許故事的腳本就由自己書寫——是否要整一個時光倒流的版本,抱得美人歸的那種?

    不整了不整了,我得不到女神,你們才歡喜,我太了解你們了。。。各位爺歡喜就好。

    附錄:IM開發(fā)干貨系列文章

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

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

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

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

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

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

    一種Android端IM智能心跳算法的設(shè)計(jì)與實(shí)現(xiàn)探討(含樣例代碼)

    移動端IM登錄時拉取數(shù)據(jù)如何作到省流量?

    通俗易懂:基于集群的移動端IM接入層負(fù)載均衡方案分享

    淺談移動端IM的多點(diǎn)登陸和消息漫游原理

    IM開發(fā)基礎(chǔ)知識補(bǔ)課(一):正確理解前置HTTP SSO單點(diǎn)登陸接口的原理

    IM開發(fā)基礎(chǔ)知識補(bǔ)課(二):如何設(shè)計(jì)大量圖片文件的服務(wù)端存儲架構(gòu)?

    IM開發(fā)基礎(chǔ)知識補(bǔ)課(三):快速理解服務(wù)端數(shù)據(jù)庫讀寫分離原理及實(shí)踐建議

    IM開發(fā)基礎(chǔ)知識補(bǔ)課(四):正確理解HTTP短連接中的Cookie、Session和Token

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

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

    IM開發(fā)基礎(chǔ)知識補(bǔ)課(五):通俗易懂,正確理解并用好MQ消息隊(duì)列

    一個低成本確保IM消息時序的方法探討

    IM開發(fā)基礎(chǔ)知識補(bǔ)課(六):數(shù)據(jù)庫用NoSQL還是SQL?讀這篇就夠了!

    IM里“附近的人”功能實(shí)現(xiàn)原理是什么?如何高效率地實(shí)現(xiàn)它?

    IM開發(fā)基礎(chǔ)知識補(bǔ)課(七):主流移動端賬號登錄方式的原理及設(shè)計(jì)思路

    IM開發(fā)基礎(chǔ)知識補(bǔ)課(八):史上最通俗,徹底搞懂字符亂碼問題的本質(zhì)

    IM的掃碼登功能如何實(shí)現(xiàn)?一文搞懂主流應(yīng)用的掃碼登陸技術(shù)原理

    IM要做手機(jī)掃碼登陸?先看看微信的掃碼登錄功能技術(shù)原理

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

    IM開發(fā)實(shí)戰(zhàn)干貨:我是如何解決大量離線聊天消息導(dǎo)致客戶端卡頓的

    IM開發(fā)干貨分享:如何優(yōu)雅的實(shí)現(xiàn)大量離線消息的可靠投遞》(* 本文)

    另外,如果您是IM開發(fā)初學(xué)者,強(qiáng)烈建議首先閱讀《新手入門一篇就夠:從零開發(fā)移動端IM》。

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



    作者:Jack Jiang (點(diǎn)擊作者姓名進(jìn)入Github)
    出處:http://www.52im.net/space-uid-1.html
    交流:歡迎加入即時通訊開發(fā)交流群 215891622
    討論:http://www.52im.net/
    Jack Jiang同時是【原創(chuàng)Java Swing外觀工程BeautyEye】【輕量級移動端即時通訊框架MobileIMSDK】的作者,可前往下載交流。
    本博文 歡迎轉(zhuǎn)載,轉(zhuǎn)載請注明出處(也可前往 我的52im.net 找到我)。


    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導(dǎo)航:
     
    Jack Jiang的 Mail: jb2011@163.com, 聯(lián)系QQ: 413980957, 微信: hellojackjiang
    主站蜘蛛池模板: 久久影视综合亚洲| 免费国产a理论片| 亚洲乱色熟女一区二区三区丝袜| 波多野结衣在线免费观看| 中文字幕视频免费在线观看| 亚洲日韩精品无码专区| 中文字幕亚洲免费无线观看日本| 亚洲国产一区二区三区| 日韩伦理片电影在线免费观看| 久久综合给合久久国产免费| 国产vA免费精品高清在线观看| www亚洲精品久久久乳| 亚洲人成影院午夜网站| 99亚洲精品高清一二区| 亚洲啪啪综合AV一区| 亚洲日韩在线中文字幕第一页| 日韩中文字幕免费| 在线A级毛片无码免费真人| 国产一卡二卡3卡四卡免费| 最近中文字幕免费完整| 久久青草91免费观看| 中文字幕的电影免费网站| 国产免费一级高清淫曰本片| 美女视频黄.免费网址| 欧洲亚洲国产精华液| 亚洲JLZZJLZZ少妇| 亚洲国产成人AV在线播放| 色老板亚洲视频免在线观| 亚洲一区电影在线观看| 亚洲一区二区三区在线| 亚洲欧洲中文日产| 亚洲免费观看网站| 精品丝袜国产自在线拍亚洲| 中文字幕亚洲男人的天堂网络| 亚洲国产日韩在线| 67194在线午夜亚洲| 中文字幕 亚洲 有码 在线| 中文字幕亚洲码在线| 亚洲AV无码片一区二区三区| 亚洲AV无码专区亚洲AV桃| 看免费毛片天天看|