<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、點評

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

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

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

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

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

    學習交流:

    - 即時通訊/推送技術(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ù)學系畢業(yè),先后就職于福建新大陸、福建富士通、北京世紀奧通。長期從事服務端軟件開發(fā),涉及SIP服務器、內(nèi)核RTP轉(zhuǎn)送、電信級AAA認證系統(tǒng)、IM即時通訊系統(tǒng)等。在分布式高性能系統(tǒng)設(shè)計有多年經(jīng)驗積累。

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

    3、相關(guān)文章

    從客戶端的角度來談談移動端IM的消息可靠性和送達機制

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

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

    IM消息送達保證機制實現(xiàn)(二):保證離線消息的可靠投遞》(* 強烈推薦

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

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

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

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

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

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

    4、正文引言

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

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

    一分鐘后,緊盯手機屏幕,等待、期盼女神回復。

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

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

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

    一個月過去了,死心。

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

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

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

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

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

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

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

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

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

    具體的思路是這樣:

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

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

    5.2 海嘯般的離線消息

    5.2.1)和平時期:

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

    5.2.2)被簽到簽死了:

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

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

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

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

    5.3 臨時運用方案

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

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

    6、遠離全量離線消息

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

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

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

    后來,給消息必達下了新的定義:

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

    打個比方:

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

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

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

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

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

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

    {

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

            uint32  session_role;

            // 會話對象的ID

            uint32        session_id;

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

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

            uint64 session_timestamp;

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

            boolis_add;

     

            // 當is_add=false時,忽略以下信息

     

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

            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)嚴正聲明:我跟她們很清白,其實我喜歡的是6379。

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

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

    App和IM后端的交互:

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

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

    {

            uint32  session_role = Role_User; //表示私聊

            uint32        session_id = 5672; //景甜的ID

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

            boolis_add = true; // true表示是更新項

            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的應答,我在App的會話列表窗口里,能看到2項更新,景甜發(fā)來的未讀消息數(shù)33條,楊冪的是5條,如下圖所示:

     

    4)點開景甜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批同步消息;或者也可以點擊tip:“↑ 33條新消息”,直接跳轉(zhuǎn)到33條消息的最舊一條,這樣支持從最舊的消息向新的翻看。

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

    主要體現(xiàn)在:

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

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

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

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

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

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

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

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

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

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

    方案缺點:邏輯復雜,客戶端增加不少工作。

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

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

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

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

    具體如下:

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

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

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

    比如以下情形:

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

    9、本文結(jié)語

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

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

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

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

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

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

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

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

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

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

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

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

    淺談移動端IM的多點登陸和消息漫游原理

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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



    作者:Jack Jiang (點擊作者姓名進入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)站導航:
     
    Jack Jiang的 Mail: jb2011@163.com, 聯(lián)系QQ: 413980957, 微信: hellojackjiang
    主站蜘蛛池模板: 亚洲综合国产成人丁香五月激情| 免费无码午夜福利片 | 91人人区免费区人人| 亚洲尹人香蕉网在线视颅| 99爱在线精品免费观看| 国产亚洲综合精品一区二区三区| 中文字幕精品亚洲无线码一区应用| 青青草无码免费一二三区| 中文字幕精品三区无码亚洲| 久久久久国产成人精品亚洲午夜| 久久成人无码国产免费播放| 亚洲日产乱码一二三区别 | 狠狠亚洲婷婷综合色香五月排名| 久久精品毛片免费观看| 欧美亚洲精品一区二区| 亚洲午夜视频在线观看| 国产又粗又长又硬免费视频| 少妇性饥渴无码A区免费 | 国产成人AV免费观看| 亚洲一卡2卡三卡4卡无卡下载 | 亚洲免费在线视频观看| 美女黄网站人色视频免费| 精品无码一区二区三区亚洲桃色 | 中文字幕在线亚洲精品| 黄页网站在线看免费| a色毛片免费视频| 亚洲AV无码专区在线电影成人| 久久亚洲AV午夜福利精品一区| 日本媚薬痉挛在线观看免费| 久久香蕉国产线看免费| 免费人成视频在线播放| 亚洲综合激情九月婷婷| 伊人亚洲综合青草青草久热| 在线a毛片免费视频观看| 最好看的中文字幕2019免费| 日韩免费在线中文字幕| 亚洲欧美日韩中文无线码| 久久亚洲精品中文字幕三区| 亚洲不卡无码av中文字幕| 免费无码AV电影在线观看| 日本免费人成网ww555在线|