<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 - 503, comments - 13, trackbacks - 0, articles - 1

    1、引言

    老讀者應該還記得我在去年國慶節前分享過一篇《技術干貨:從零開始,教你設計一個百萬級的消息推送系統》,雖然我在文中有貼一些偽代碼,依然有些朋友希望能直接分享一些可以運行的源碼。好吧,質疑我窮我無話可說(因為是真窮。。),懷疑我擼碼的能力那是絕對不行,所以這次準備拉起鍵盤大干一場——徒手擼套分布式IM出來!^_^!

    本文記錄了我開發的一款面向IM學習者的 IM系統——CIM(全稱:CROSS-IM),同時提供了一些組件幫助開發者構建一款屬于自己可水平擴展的 IM。

    通過學習本文和CIM代碼,你可以獲得以下知識:

    1)如何從頭開發一套IM(CIM的客戶有點弱,見諒見諒);

    2)如何設計分布式的IM架構;

    3)如何將你的分布式IM架構用代碼和相關技術實現出來。

    本文配套的CIM源碼地址:

    主要鏡像:https://github.com/crossoverJie/cim

    備用鏡像:https://github.com/52im/cim

    以下文章與本文類似或相關,同樣有助于您的IM開發入門:

    * 友情提示:閱讀本文和CIM源碼,需要您具備一定的網絡編程、IM理論等知識等,如果您還不具備這些,請先閱讀《新手入門一篇就夠:從零開發移動端IM》,完全來的及!

    學習交流:

    - 即時通訊/推送技術開發交流5群:215477170[推薦]

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

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

    2、關于作者

    crossoverJie(陳杰): 90后,畢業于重慶信息工程學院,現供職于重慶豬八戒網絡有限公司。

    3、運行演示

    本次特地錄了兩段視頻演示(群聊、私聊),點擊下方鏈接可以查看視頻版 Demo。

    CIM 私聊視頻演示:https://www.bilibili.com/video/av39405821

    CIM 群聊視頻演示:https://www.bilibili.com/video/av39405501

    4、架構設計

    下面來看看具體的架構設計:

    架構說明:

    1)CIM 中的各個組件均采用 SpringBoot 構建;

    2)采用 Netty + Google Protocol Buffer 構建底層通信;

    3)Redis 存放各個客戶端的路由信息、賬號信息、在線狀態等;

    4)Zookeeper 用于 IM-server 服務的注冊與發現。

    整體主要由以下模塊組成:

    1)cim-server——IM 服務端:用于接收 client 連接、消息透傳、消息推送等功能。支持集群部署;

    2)cim-forward-route——消息路由服務器:用于處理消息路由、消息轉發、用戶登錄、用戶下線以及一些運營工具(獲取在線用戶數等);

    3)cim-client——IM 客戶端:給用戶使用的消息終端,一個命令即可啟動并向其他人發起通訊(群聊、私聊);同時內置了一些常用命令方便使用。

    5、邏輯流程圖

    整體的流程也比較簡單,流程圖如下:

    流程解釋如下:

    1)客戶端向 route 發起登錄;

    2)登錄成功從 Zookeeper 中選擇可用 IM-server 返回給客戶端,并保存登錄、路由信息到 Redis;

    3)客戶端向 IM-server 發起長連接,成功后保持心跳;

    4)客戶端下線時通過 route 清除狀態信息。

    所以當我們自己部署時需要以下步驟:

    1)搭建基礎中間件 RedisZookeeper

    2)部署 cim-server,這是真正的 IM 服務器,為了滿足性能需求所以支持水平擴展,只需要注冊到同一個 Zookeeper 即可;

    3)部署 cim-forward-route,這是路由服務器,所有的消息都需要經過它。由于它是無狀態的,所以也可以利用 Nginx 代理提高可用性;

    4)cim-client 真正面向用戶的客戶端;啟動之后會自動連接 IM 服務器便可以在控制臺收發消息了。

    更多使用介紹可以參考快速啟動

    接下來各章將重點看看具體的詳細設計實現,比如群聊、私聊消息如何流轉;IM 服務端負載均衡;服務如何注冊發現等等。

    6、IM 服務端

    先來看看服務端:主要是實現客戶端上下線、消息下發等功能。

    首先是服務啟動:

    由于是在 SpringBoot 中搭建的,所以在應用啟動時需要啟動 Netty 服務。

    從 pipline 中可以看出使用了 Protobuf 的編解碼(具體報文在客戶端中分析,相關知識請見:《Protobuf通信協議詳解:代碼演示、詳細原理介紹等》)。

    7、注冊發現

    需要滿足 IM 服務端的水平擴展需求,所以 cim-server 是需要將自身數據發布到注冊中心的。這里參考之前分享的《搞定服務注冊與發現》有具體介紹。

    所以在應用啟動成功后需要將自身數據注冊到 Zookeeper 中:

    最主要的目的就是將當前應用的 ip + cim-server-port+ http-port 注冊上去:

    上圖是我在演示環境中注冊的兩個 cim-server 實例(由于在一臺服務器,所以只是端口不同)。這樣在客戶端(監聽這個 Zookeeper 節點)就能實時的知道目前可用的服務信息。

    8、登錄

    當客戶端請求 cim-forward-route 中的登錄接口(詳見下文)做完業務驗證(就相當于日常登錄其他網站一樣)之后,客戶端會向服務端發起一個長連接。

    如之前的流程所示:

    這時客戶端會發送一個特殊報文,表明當前是登錄信息。服務端收到后就需要將該客戶端的 userID 和當前 Channel 通道關系保存起來。

    同時也緩存了用戶的信息,也就是 userID 和 用戶名。

    9、離線消息

    當客戶端斷線后也需要將剛才緩存的信息清除掉。

    同時也需要調用 route 接口清除相關信息(具體接口看下文)。

    10、IM 路由

    從架構圖中可以看出,路由層是非常重要的一環;它提供了一系列的 HTTP 服務承接了客戶端和服務端。

    目前主要是以下幾個接口。

    10.1 注冊接口

    由于每一個客戶端都是需要登錄才能使用的,所以第一步自然是注冊。

    這里就設計的比較簡單,直接利用 Redis 來存儲用戶信息;用戶信息也只有 ID 和 userName 而已。只是為了方便查詢在 Redis 中的 KV 又反過來存儲了一份 VK,這樣 ID 和 userName 都必須唯一。

    10.2 登錄接口

    這里的登錄和 cim-server 中的登錄不一樣,具有業務性質:

    具體的流程:

    1)登錄成功之后需要判斷是否是重復登錄(一個用戶只能運行一個客戶端);

    2)登錄成功后需要從 Zookeeper 中獲取服務列表(cim-server)并根據某種算法選擇一臺服務返回給客戶端;

    3)登錄成功之后還需要保存路由信息,也就是當前用戶分配的服務實例保存到 Redis 中。

    為了實現只能一個用戶登錄,使用了 Redis 中的 set 來保存登錄信息;利用 userID 作為 key ,重復的登錄就會寫入失敗。


    類似于 Java 中的 HashSet,只能去重保存。

    獲取一臺可用的路由實例也比較簡單:

    1)先從 Zookeeper 獲取所有的服務實例做一個內部緩存;

    2)輪詢選擇一臺服務器(目前只有這一種算法,后續會新增)。

    當然要獲取 Zookeeper 中的服務實例前自然是需要監聽 cim-server 之前注冊上去的那個節點。

    具體代碼如下:

    也是在應用啟動之后監聽 Zookeeper 中的路由節點,一旦發生變化就會更新內部緩存。這里使用的是 Guava 的 cache,它基于 ConcurrentHashMap,所以可以保證清除、新增緩存的原子性。

    10.3 群聊接口

    這是一個真正發消息的接口,實現的效果就是其中一個客戶端發消息,其余所有客戶端都能收到!流程肯定是客戶端發送一條消息到服務端,服務端收到后在上文介紹的 SessionSocketHolder 中遍歷所有 Channel(通道)然后下發消息即可。服務端是單機倒也可以,但現在是集群設計。所以所有的客戶端會根據之前的輪詢算法分配到不同的 cim-server 實例中。

    因此就需要路由層來發揮作用了。

    路由接口收到消息后首先遍歷出所有的客戶端和服務實例的關系。

    路由關系在 Redis 中的存放如下:

    由于 Redis 單線程的特質,當數據量大時;一旦使用 keys 匹配所有 cim-route:* 數據,會導致 Redis 不能處理其他請求。所以這里改為使用 scan 命令來遍歷所有的 cim-route:*。

    接著會挨個調用每個客戶端所在的服務端的 HTTP 接口用于推送消息。

    在 cim-server 中的實現如下:

    cim-server 收到消息后會在內部緩存中查詢該 userID 的通道,接著只需要發消息即可。

    10.4 在線用戶接口

    這是一個輔助接口,可以查詢出當前在線用戶信息。

    實現也很簡單,也就是查詢之前保存 ”用戶登錄狀態的那個去重 set “即可。

    10.5 私聊接口

    之所以說獲取在線用戶是一個輔助接口,其實就是用于輔助私聊使用的。一般我們使用私聊的前提肯定得知道當前哪些用戶在線,接著你才會知道你要和誰進行私聊。

    類似于這樣:

    在我們這個場景中,私聊的前提就是需要獲得在線用戶的 userID:

    所以私聊接口在收到消息后需要查詢到接收者所在的 cim-server 實例信息,后續的步驟就和群聊一致了。調用接收者所在實例的 HTTP 接口下發信息。只是群聊是遍歷所有的在線用戶,私聊只發送一個的區別。

    10.6 下線接口

    一旦客戶端下線,我們就需要將之前存放在 Redis 中的一些信息刪除掉(路由信息、登錄狀態)。

    11、IM 客戶端

    客戶端中的一些邏輯其實在上文已經談到一些了。

    11.1 登錄

    第一步也就是登錄,需要在啟動時調用 route 的登錄接口,獲得 cim-server 信息再創建連接。

    登錄過程中 route 接口會判斷是否為重復登錄,重復登錄則會直接退出程序。

    接下來是利用 route 接口返回的 cim-server 實例信息(ip+port)創建連接。最后一步就是發送一個登錄標志的信息到服務端,讓它保持客戶端和 Channel 的關系。

    11.2 自定義協議

    上文提到的一些登錄報文、真正的消息報文這些其實都是在我們自定義協議中可以區別出來的。由于是使用 Google Protocol Buffer 編解碼,所以先看看原始格式。

    其實這個協議中目前一共就三個字段:

    1)requestId 可以理解為 userId;

    2)reqMsg 就是真正的消息;

    3)type 也就是上文提到的消息類別。

    目前主要是三種類型,分別對應不同的業務:

    11.3 心跳

    為了保持客戶端和服務端的連接,每隔一段時間沒有發送消息都需要自動的發送心跳。

    目前的策略是每隔一分鐘就是發送一個心跳包到服務端:

    這樣服務端每隔一分鐘沒有收到業務消息時就會收到 ping 的心跳包:

    11.4 內置命令

    客戶端也內置了一些基本命令來方便使用。

    比如輸入 :q 就會退出客戶端,同時會關閉一些系統資源。

    當輸入 :olu(onlineUser 的簡寫)就會去調用 route 的獲取所有在線用戶接口。

    11.5 群聊

    群聊的使用非常簡單,只需要在控制臺輸入消息回車即可。這時會去調用 route 的群聊接口。

    11.6 私聊

    私聊也是同理,但前提是需要觸發關鍵字;使用 userId;;消息內容 這樣的格式才會給某個用戶發送消息,所以一般都需要先使用 

    lu 命令獲取所以在線用戶才方便使用。

    11.7 消息回調

    為了滿足一些定制需求,比如消息需要保存之類的。所以在客戶端收到消息之后會回調一個接口,在這個接口中可以自定義實現。

    因此先創建了一個 caller 的 bean,這個 bean 中包含了一個 CustomMsgHandleListener 接口,需要自行處理只需要實現此接口即可。

    11.8 自定義界面

    由于我自己不怎么會寫界面,但保不準有其他大牛會寫。所以客戶端中的群聊、私聊、獲取在線用戶、消息回調等業務(以及之后的業務)都是以接口形式提供。

    也方便后面做頁面集成,只需要調這些接口就行了;具體實現不用怎么關心。

    12、本文小結

    cim 目前只是第一版,BUG 多,功能少(只拉了幾個群友做了測試);不過后續還會接著完善,至少這一版會給那些沒有相關經驗的朋友帶來一些思路。

    后續計劃:

    附錄:更多IM相關文章

    [1] 有關IM代碼實踐的文章:
    自已開發IM有那么難嗎?手把手教你自擼一個Andriod版簡易IM (有源碼)
    一種Android端IM智能心跳算法的設計與實現探討(含樣例代碼)
    手把手教你用Netty實現網絡通信程序的心跳機制、斷線重連機制
    詳解Netty的安全性:原理介紹、代碼演示(上篇)
    詳解Netty的安全性:原理介紹、代碼演示(下篇)
    微信本地數據庫破解版(含iOS、Android),僅供學習研究 [附件下載]
    Java NIO基礎視頻教程、MINA視頻教程、Netty快速入門視頻 [有源碼]
    輕量級即時通訊框架MobileIMSDK的iOS源碼(開源版)[附件下載]
    開源IM工程“蘑菇街TeamTalk”2015年5月前未刪減版完整代碼 [附件下載]
    微信本地數據庫破解版(含iOS、Android),僅供學習研究 [附件下載]
    NIO框架入門(一):服務端基于Netty4的UDP雙向通信Demo演示 [附件下載]
    NIO框架入門(二):服務端基于MINA2的UDP雙向通信Demo演示 [附件下載]
    NIO框架入門(三):iOS與MINA2、Netty4的跨平臺UDP雙向通信實戰 [附件下載]
    NIO框架入門(四):Android與MINA2、Netty4的跨平臺UDP雙向通信實戰 [附件下載]
    用于IM中圖片壓縮的Android工具類源碼,效果可媲美微信 [附件下載]
    高仿Android版手機QQ可拖拽未讀數小氣泡源碼 [附件下載]
    一個WebSocket實時聊天室Demo:基于node.js+socket.io [附件下載]
    Android聊天界面源碼:實現了聊天氣泡、表情圖標(可翻頁) [附件下載]
    高仿Android版手機QQ首頁側滑菜單源碼 [附件下載]
    開源libco庫:單機千萬連接、支撐微信8億用戶的后臺框架基石 [源碼下載]
    分享java AMR音頻文件合并源碼,全網最全
    微信團隊原創Android資源混淆工具:AndResGuard [有源碼]
    一個基于MQTT通信協議的完整Android推送Demo [附件下載]
    Android版高仿微信聊天界面源碼 [附件下載]
    高仿手機QQ的Android版鎖屏聊天消息提醒功能 [附件下載]
    高仿iOS版手機QQ錄音及振幅動畫完整實現 [源碼下載]
    Android端社交應用中的評論和回復功能實戰分享[圖文+源碼]
    Android端IM應用中的@人功能實現:仿微博、QQ、微信,零入侵、高可擴展[圖文+源碼]
    仿微信的IM聊天時間顯示格式(含iOS/Android/Web實現)[圖文+源碼]
    Android版仿微信朋友圈圖片拖拽返回效果 [源碼下載]
    適合新手:從零開發一個IM服務端(基于Netty,有完整源碼)
    拉起鍵盤就是干:跟我一起徒手擼一套分布式IM系統
    >> 更多同類文章 …… 

    [2] 有關IM架構設計的文章:
    淺談IM系統的架構設計
    簡述移動端IM開發的那些坑:架構設計、通信協議和客戶端
    一套海量在線用戶的移動端IM架構設計實踐分享(含詳細圖文)
    一套原創分布式即時通訊(IM)系統理論架構方案
    從零到卓越:京東客服即時通訊系統的技術架構演進歷程
    蘑菇街即時通訊/IM服務器開發之架構選擇
    騰訊QQ1.4億在線用戶的技術挑戰和架構演進之路PPT
    微信后臺基于時間序的海量數據冷熱分級架構設計實踐
    微信技術總監談架構:微信之道——大道至簡(演講全文)
    如何解讀《微信技術總監談架構:微信之道——大道至簡》
    快速裂變:見證微信強大后臺架構從0到1的演進歷程(一)
    17年的實踐:騰訊海量產品的技術方法論
    移動端IM中大規模群消息的推送如何保證效率、實時性?
    現代IM系統中聊天消息的同步和存儲方案探討
    IM開發基礎知識補課(二):如何設計大量圖片文件的服務端存儲架構?
    IM開發基礎知識補課(三):快速理解服務端數據庫讀寫分離原理及實踐建議
    IM開發基礎知識補課(四):正確理解HTTP短連接中的Cookie、Session和Token
    WhatsApp技術實踐分享:32人工程團隊創造的技術神話
    微信朋友圈千億訪問量背后的技術挑戰和實踐總結
    王者榮耀2億用戶量的背后:產品定位、技術架構、網絡方案等
    IM系統的MQ消息中間件選型:Kafka還是RabbitMQ?
    騰訊資深架構師干貨總結:一文讀懂大型分布式系統設計的方方面面
    以微博類應用場景為例,總結海量社交系統的架構設計步驟
    快速理解高性能HTTP服務端的負載均衡技術原理
    子彈短信光鮮的背后:網易云信首席架構師分享億級IM平臺的技術實踐
    知乎技術分享:從單機到2000萬QPS并發的Redis高性能緩存實踐之路
    IM開發基礎知識補課(五):通俗易懂,正確理解并用好MQ消息隊列
    微信技術分享:微信的海量IM聊天消息序列號生成實踐(算法原理篇)
    微信技術分享:微信的海量IM聊天消息序列號生成實踐(容災方案篇)
    新手入門:零基礎理解大型分布式架構的演進歷史、技術原理、最佳實踐
    一套高可用、易伸縮、高并發的IM群聊、單聊架構方案設計實踐
    阿里技術分享:深度揭秘阿里數據庫技術方案的10年變遷史
    阿里技術分享:阿里自研金融級數據庫OceanBase的艱辛成長之路
    社交軟件紅包技術解密(一):全面解密QQ紅包技術方案——架構、技術實現等
    社交軟件紅包技術解密(二):解密微信搖一搖紅包從0到1的技術演進
    社交軟件紅包技術解密(三):微信搖一搖紅包雨背后的技術細節
    社交軟件紅包技術解密(四):微信紅包系統是如何應對高并發的
    社交軟件紅包技術解密(五):微信紅包系統是如何實現高可用性的
    社交軟件紅包技術解密(六):微信紅包系統的存儲層架構演進實踐
    社交軟件紅包技術解密(七):支付寶紅包的海量高并發技術實踐
    社交軟件紅包技術解密(八):全面解密微博紅包技術方案
    社交軟件紅包技術解密(九):談談手Q紅包的功能邏輯、容災、運維、架構等
    即時通訊新手入門:一文讀懂什么是Nginx?它能否實現IM的負載均衡?
    即時通訊新手入門:快速理解RPC技術——基本概念、原理和用途
    多維度對比5款主流分布式MQ消息隊列,媽媽再也不擔心我的技術選型了
    從游擊隊到正規軍:馬蜂窩旅游網的IM系統架構演進之路
    IM開發基礎知識補課(六):數據庫用NoSQL還是SQL?讀這篇就夠了!
    >> 更多同類文章 ……

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



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


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


    網站導航:
     
    Jack Jiang的 Mail: jb2011@163.com, 聯系QQ: 413980957, 微信: hellojackjiang
    主站蜘蛛池模板: 亚洲成人福利在线观看| 免费一级特黄特色大片在线| 中文字幕免费视频| 国产情侣久久久久aⅴ免费| 黄色视屏在线免费播放| 午夜免费国产体验区免费的| 五月婷婷免费视频| 亚洲一级片免费看| 97在线免费视频| 嫩草成人永久免费观看| 无码一区二区三区免费| 精品一区二区三区免费毛片爱| 最近2019中文字幕免费大全5| 久久久久久一品道精品免费看| 久久免费观看国产精品| 久久精品人成免费| 成人午夜免费福利视频| 最近最新的免费中文字幕| 黑人粗长大战亚洲女2021国产精品成人免费视频| 国产麻豆视频免费观看| 日韩a级毛片免费观看| 免费国产精品视频| 精品国产亚洲一区二区在线观看 | jizz日本免费| a级毛片免费全部播放| 日韩精品极品视频在线观看免费| 1000部啪啪未满十八勿入免费| 成人免费黄色网址| 永久黄网站色视频免费直播| 亚洲男人av香蕉爽爽爽爽| 亚洲精品国产美女久久久| 亚洲精品无码久久久久久久| 亚洲性色AV日韩在线观看| 免费大片av手机看片高清| 国产免费无码AV片在线观看不卡| 亚洲精品视频在线观看免费| 日韩午夜免费视频| 亚洲区小说区图片区QVOD| 亚洲国产中文在线视频| 免费播放国产性色生活片| 99久久免费观看|