Jack Jiang

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

          本文原題“搭建高性能的IM系統(tǒng)”,作者“劉蒞”,內(nèi)容有修訂和改動(dòng)。為了尊重原創(chuàng),如需轉(zhuǎn)載,請(qǐng)聯(lián)系作者獲得授權(quán)。

          1、引言

          相信很多朋友對(duì)微信、QQ等聊天軟件的實(shí)現(xiàn)原理都非常感興趣,筆者同樣對(duì)這些軟件有著深厚的興趣。而且筆者在公司也是做IM的,公司的IM每天承載著上億條消息的發(fā)送!

          正好有這樣的技術(shù)資源和條件,所以前段時(shí)間,筆者利用業(yè)余時(shí)間,基于Netty開(kāi)發(fā)了一套基本功能比較完善的IM系統(tǒng)。該系統(tǒng)支持私聊、群聊、會(huì)話管理、心跳檢測(cè),支持服務(wù)注冊(cè)、負(fù)載均衡,支持任意節(jié)點(diǎn)水平擴(kuò)容。

          這段時(shí)間,網(wǎng)上的一些讀者,也希望筆者分享一些Netty或者IM相關(guān)的知識(shí),所以今天筆者把開(kāi)發(fā)的這套IM系統(tǒng)分享給大家。

          本文將根據(jù)筆者這次的業(yè)余技術(shù)實(shí)踐,為你講述如何基于Netty+Zk+Redis來(lái)搭建一套高性能IM集群,包括本次實(shí)現(xiàn)IM集群的技術(shù)原理和實(shí)例代碼,希望能帶給你啟發(fā)。

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

          - 移動(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-3816-1-1.html )

          2、本文源碼

          主地址:https://github.com/nicoliuli/chat

          備地址:https://github.com/52im/chat

          源碼的目錄結(jié)構(gòu),如下圖所示:

          3、知識(shí)準(zhǔn)備

          * 重要提示:本文不是一篇即時(shí)通訊理論文章,文章內(nèi)容來(lái)自代碼實(shí)戰(zhàn),如果你對(duì)即時(shí)通訊(IM)技術(shù)理論了解的太少,建議先詳細(xì)閱讀:《新手入門(mén)一篇就夠:從零開(kāi)發(fā)移動(dòng)端IM》。

          可能有人不知道 Netty 是什么,這里簡(jiǎn)單介紹下:

          Netty 是一個(gè) Java 開(kāi)源框架。Netty 提供異步的、事件驅(qū)動(dòng)的網(wǎng)絡(luò)應(yīng)用程序框架和工具,用以快速開(kāi)發(fā)高性能、高可靠性的網(wǎng)絡(luò)服務(wù)器和客戶端程序。

          也就是說(shuō),Netty 是一個(gè)基于 NIO 的客戶、服務(wù)器端編程框架,使用Netty 可以確保你快速和簡(jiǎn)單的開(kāi)發(fā)出一個(gè)網(wǎng)絡(luò)應(yīng)用,例如實(shí)現(xiàn)了某種協(xié)議的客戶,服務(wù)端應(yīng)用。

          Netty 相當(dāng)簡(jiǎn)化和流線化了網(wǎng)絡(luò)應(yīng)用的編程開(kāi)發(fā)過(guò)程,例如,TCP 和 UDP 的 Socket 服務(wù)開(kāi)發(fā)。

          以下是有關(guān)Netty的入門(mén)文章:

          如果你連Java的NIO都不知道是什么,下面的文章建議優(yōu)先讀:

          Netty源碼和API的在線查閱地址:

          4、系統(tǒng)架構(gòu)

          系統(tǒng)的架構(gòu)如上圖所示:整個(gè)系統(tǒng)是一個(gè)C/S系統(tǒng),客戶端沒(méi)有做復(fù)雜的圖形化界面而是用Java終端開(kāi)發(fā)的(黑窗口),服務(wù)端IM實(shí)例是Netty寫(xiě)的socket服務(wù)。

          ZK作為服務(wù)注冊(cè)中心,Redis用來(lái)做分布式會(huì)話的緩存,并保存用戶信息和輕量級(jí)的消息隊(duì)列。

          對(duì)于整個(gè)系統(tǒng)架構(gòu)中各部分的工作原理,我們將在接下來(lái)的各章節(jié)中一一介紹。

          5、服務(wù)端的工作原理

          在上述架構(gòu)中:NettyServer啟動(dòng),每啟動(dòng)一臺(tái)Server節(jié)點(diǎn),都會(huì)把自身的節(jié)點(diǎn)信息,如:ip、port等信息注冊(cè)到ZK上(臨時(shí)節(jié)點(diǎn))。

          正如上節(jié)架構(gòu)圖上啟動(dòng)了兩臺(tái)NettyServer,所以ZK上會(huì)保存兩個(gè)Server的信息。

          同時(shí)ZK將監(jiān)聽(tīng)每臺(tái)Server節(jié)點(diǎn),如果Server宕機(jī)ZK就會(huì)刪除當(dāng)前機(jī)器所注冊(cè)的信息(把臨時(shí)節(jié)點(diǎn)刪除),這樣就完成了簡(jiǎn)單的服務(wù)注冊(cè)的功能。

          6、客戶端的工作原理

          Client啟動(dòng)時(shí),會(huì)先從ZK上隨機(jī)選擇一個(gè)可用的NettyServer(隨機(jī)表示可以實(shí)現(xiàn)負(fù)載均衡),拿到NettyServer的信息(IP和port)后與NettyServer建立鏈接。

          鏈接建立起來(lái)后,NettyServer端會(huì)生成一個(gè)Session(即會(huì)話),用來(lái)把當(dāng)前客戶端的Channel等信息組裝成一個(gè)Session對(duì)象,保存在一個(gè)SessionMap里,同時(shí)也會(huì)把這個(gè)Session保存在Redis中。

          這個(gè)會(huì)話特別重要,通過(guò)會(huì)話,我們能獲取當(dāng)前Client和NettyServer的Channel等信息。

          7、Session的作用

          我們啟動(dòng)多個(gè)Client,由于每個(gè)Client啟動(dòng),都會(huì)先從ZK上隨機(jī)獲取NettyServer的的信息,所以如果啟動(dòng)多個(gè)Client,就會(huì)連接到不同的NettyServer上。

          熟悉Netty的朋友都知道,Client與Server建立接連后會(huì)產(chǎn)生一個(gè)Channel,通過(guò)Channel,Client和Server才能進(jìn)行正常的網(wǎng)絡(luò)數(shù)據(jù)傳輸。

          如果Client1和Client2連接在同一個(gè)Server上:那么Server通過(guò)SessionMap分別拿到Client1和Client2的會(huì)話,會(huì)話中包含Channel信息,有了兩個(gè)Client的Channel,Client1和Client2便可完成消息通信。

          如果Client1和Client2連接到不同的NettyServer上:Client1和Client2要進(jìn)行通信,該怎么辦?這個(gè)問(wèn)題放在后面解答。

          8、高效的數(shù)據(jù)傳輸

          無(wú)論是IM系統(tǒng),還是分布式的RPC框架,高效的網(wǎng)絡(luò)數(shù)據(jù)傳輸,無(wú)疑會(huì)極大的提升系統(tǒng)的性能。

          數(shù)據(jù)通過(guò)網(wǎng)絡(luò)傳輸時(shí),一般把對(duì)象通序列化成二進(jìn)制字節(jié)流數(shù)組,然后將數(shù)據(jù)通過(guò)socket傳給對(duì)方服務(wù)器,對(duì)方服務(wù)器拿到二進(jìn)制字節(jié)流后再反序列化成對(duì)象,達(dá)到遠(yuǎn)程通信的目的。

          在Java領(lǐng)域,Java序列化對(duì)象的方式有嚴(yán)重的性能問(wèn)題,業(yè)界常用谷歌的protobuf來(lái)實(shí)現(xiàn)序列化反序列化(見(jiàn)《Protobuf通信協(xié)議詳解:代碼演示、詳細(xì)原理介紹等)。

          protobuf支持不同的編程語(yǔ)言,可以實(shí)現(xiàn)跨語(yǔ)言的系統(tǒng)調(diào)用,并且有著極高的序列化反序列化性能,本系統(tǒng)也采用protobuf來(lái)做數(shù)據(jù)的序列化。

          關(guān)于Protobuf的基本認(rèn)之,下面這幾篇可以深入讀一讀:

          1. 強(qiáng)列建議將Protobuf作為你的即時(shí)通訊應(yīng)用數(shù)據(jù)傳輸格式
          2. 全方位評(píng)測(cè):Protobuf性能到底有沒(méi)有比JSON快5倍?
          3. 金蝶隨手記團(tuán)隊(duì)分享:還在用JSON? Protobuf讓數(shù)據(jù)傳輸更省更快(原理篇)

          另外:一套海量在線用戶的移動(dòng)端IM架構(gòu)設(shè)計(jì)實(shí)踐分享(含詳細(xì)圖文)》一文中,“3、協(xié)議設(shè)計(jì)”這一節(jié)有關(guān)于protobuf在IM中的實(shí)戰(zhàn)設(shè)計(jì)和使用,可以一并學(xué)習(xí)一下。

          9、聊天協(xié)議定義

          我們?cè)谑褂酶鞣N聊天APP時(shí),會(huì)發(fā)各種各樣的消息,每種消息都會(huì)對(duì)應(yīng)不同的消息格式(即“聊天協(xié)議”)。

          聊天協(xié)議中主要包含幾種重要的信息:

          • 1)消息類(lèi)型;
          • 2)發(fā)送時(shí)間;
          • 3)消息的收發(fā)人;
          • 4)聊天類(lèi)型(群聊或私聊)。

          我的這套IM系統(tǒng)中,聊天協(xié)議定義如下:

          syntax = "proto3";

          option java_package = "model.chat";

          option java_outer_classname = "RpcMsg";

          message Msg{

              string msg_id = 1;

              int64 from_uid = 2;

              int64 to_uid = 3;

              int32 format = 4;

              int32 msg_type = 5;

              int32 chat_type = 6;

              int64 timestamp = 7;

              string body = 8;

              repeated int64 to_uid_list = 9;

          }

          如上面的protobuf代碼,字段的具體含義如下:

          • 1)msg_id:表示消息的唯一id,可以用UUID表示;
          • 2)from_uid:消息發(fā)送者的uid;
          • 3)to_uid:消息接收者的uid;
          • 4)format:消息格式,我們使用各種聊天軟件時(shí),會(huì)發(fā)送文字消息,語(yǔ)音消息,圖片消息等等等等,每種消息有不同的消息格式,我們用format來(lái)表示(由于本系統(tǒng)是java終端,format字段沒(méi)有太大含義,可有可無(wú));
          • 5)msg_type:消息類(lèi)型,比如登錄消息、聊天消息、ack消息、ping、pong消息;
          • 6)chat_type:聊天類(lèi)型,如群聊、私聊;
          • 7)timestamp:發(fā)送消息的時(shí)間戳;
          • 8)body:消息的具體內(nèi)容,載體;
          • 9)to_uid_list:這個(gè)字段用戶群聊消息提高群聊消息的性能,具體作用會(huì)在群聊原理部分詳細(xì)解釋。

          10、私聊消息發(fā)送原理

          Client1給Client2發(fā)消息時(shí),我們需要構(gòu)建上節(jié)中的消息體。

          具體就是:from_uid是Client1的uid、to_uid是Client2的uid。

          NettyServer收到消息后的處理邏輯是:

          • 1)解析到to_uid字段;
          • 2)從SessionMap或者Redis中保存的Session集合中獲取to_uid即Client2的Session;
          • 3)從Session中取出Client2的Channel;
          • 4)然后將消息通過(guò)Client2的Channel發(fā)給Client2。

          11、群聊消息發(fā)送原理

          群聊消息的分發(fā)通常有兩種技術(shù)實(shí)現(xiàn)方式,我們一一來(lái)看看。

          方式一:假設(shè)一個(gè)群有100人,如果Client1給一個(gè)群的所有人發(fā)消息,其實(shí)相當(dāng)于Client1分別給其余99人分別發(fā)一條消息。我們可以直接在Client端,通過(guò)循環(huán),分別給群里的99人發(fā)消息即可,相當(dāng)于Client發(fā)送給NettyServer發(fā)送了99次相同的消息(除了to_uid不同)。

          上述方案有很?chē)?yán)重的性能問(wèn)題:Client1通過(guò)循環(huán)99次,分別把消息發(fā)給NettyServer,NettyServer收到這99條消息后,分別將消息發(fā)給群內(nèi)其余的用戶。先拋開(kāi)移動(dòng)端的特殊性(比如循環(huán)還沒(méi)完成手機(jī)就有可能退到后臺(tái)被系統(tǒng)掛起),顯然Client1到NettyServer的99次循環(huán)存在明顯不合理地方。

          方式二:上節(jié)的消息體中to_uid_list字段就是為了解決這個(gè)方式一的性能問(wèn)題的。Client1把群內(nèi)其余99個(gè)Client的uid保存在to_uid_list中,然后NettyServer只發(fā)一條消息,NettyServer收到這一條消息后,通過(guò)to_uid_list字段解析群內(nèi)其余99的Client的uid,再通過(guò)循環(huán)把消息分別發(fā)送給群內(nèi)其余的Client。

          可以看到:方式二的群聊時(shí),Client1與NettyServer只進(jìn)行1次消息傳輸,相比于方式一,效率提高了50%。

          11、技術(shù)關(guān)鍵點(diǎn)1:客戶端分別連接在不同IM實(shí)例時(shí)如何通信?

          針對(duì)本文中的架構(gòu),如果多個(gè)Client分別連接在不同的Server上,Client之間應(yīng)該如何通信呢?

          為了回答這個(gè)問(wèn)題,我們首先要明白Session的作用。

          我們做過(guò)JavaWeb開(kāi)發(fā)的朋友都知道,Session用來(lái)保存用戶的登錄信息。

          在IM系統(tǒng)中也是如此:Session中保存用戶的Channel信息。當(dāng)Client與Server建立鏈接成功后,會(huì)產(chǎn)生一個(gè)Channel,Client和Server是通過(guò)Channel,實(shí)現(xiàn)數(shù)據(jù)傳輸。當(dāng)兩端鏈接建立起來(lái)后,Server會(huì)構(gòu)建出一個(gè)Session對(duì)象,保存uid和Channel等信息,并把這個(gè)Session保存在一個(gè)SessionMap里(NettyServer的內(nèi)存里),uid為key,我們可以通過(guò)uid就可以找到這個(gè)uid對(duì)應(yīng)的Session。

          但只有SessionMap還不夠:我們需要利用Redis,它的作用是保存整個(gè)NettyServer集群全部鏈接成功的用戶,這也是一種Session,但這種Session沒(méi)有保存uid和Channel的對(duì)應(yīng)關(guān)系,而是保存Client鏈接到NettyServer的信息,如Client鏈接到的這個(gè)NettyServer的ip、port等。通過(guò)uid,我們同樣可以從Redis中拿到當(dāng)前Client鏈接到的NettyServer的信息。正是有了這個(gè)信息,我們才能做到,NettyServer集群任意節(jié)點(diǎn)水平擴(kuò)容。

          當(dāng)用戶量少的時(shí)候:我們只需要一臺(tái)NettyServer節(jié)點(diǎn)便可以扛住流量,所有的Client鏈接到同一個(gè)NettyServer上,并在NettyServer的SessionMap中保存每個(gè)Client的會(huì)話。Client1與Client2通信時(shí),Client1把消息發(fā)給NettyServer,NettyServer從SessionMap中取出Client2的Session和Channel,將消息發(fā)給Client2。

          隨著用戶量不斷增多:一臺(tái)NettyServer不夠,我們?cè)黾恿藥着_(tái)NettyServer,這時(shí)Client1鏈接到NettyServer1上并在SessionMap和Redis中保存了會(huì)話和Client1的鏈接信息,Client2鏈接到NettyServer2上并在SessionMap和Redis中保存了會(huì)話和Client2的鏈接信息。Client1給Client2發(fā)消息時(shí),通過(guò)NettyServer1的SessionMap找不到Client2的會(huì)話,消息無(wú)法發(fā)送,于是便從Redis中獲取Client2鏈接在哪臺(tái)NettyServer上。獲取到Client2所鏈接的NettyServer信息后,我們可以把消息轉(zhuǎn)發(fā)給NettyServer2,NettyServer2收到消息后,從NettyServer2的SessionMap中獲取Client2的Session和Channel,然后將消息發(fā)送給Client2。

          那么:NettyServer1的消息如何轉(zhuǎn)發(fā)給NettyServer2呢?答案是通過(guò)消息隊(duì)列,如Redis中的list數(shù)據(jù)結(jié)構(gòu)。每臺(tái)NettyServer啟動(dòng)后都需要監(jiān)聽(tīng)一個(gè)自己的Redis中的消息隊(duì)列,這個(gè)隊(duì)列用戶接收其他NettyServer轉(zhuǎn)發(fā)給當(dāng)前NettyServer的消息。

          * Jack Jiang點(diǎn)評(píng):上述集群方案中,Redis既作為在線用戶列表存儲(chǔ)中心,又作為集群中不同IM長(zhǎng)連接實(shí)例的消息中轉(zhuǎn)服務(wù)(此時(shí)的Redis作用相當(dāng)于MQ),那Redis不就成為了整個(gè)分布式集群的單點(diǎn)瓶頸了嗎?

          12、技術(shù)關(guān)鍵點(diǎn)2:鏈接斷開(kāi),如何處理?

          如果Client與NettyServer,由于某種原因(客戶端退出、服務(wù)端重啟、網(wǎng)絡(luò)因素等)斷開(kāi)鏈接,我們必須要從SessionMap刪除會(huì)話和Redis中保留的數(shù)據(jù)。

          如果不清除這兩類(lèi)數(shù)據(jù)的話,很有可能Client1發(fā)送給Client2的消息,可能會(huì)發(fā)給其他用戶,或者就算Client2處于登錄狀態(tài),Client2也收到不到消息。

          我們可以在Netty框架中的channelInactive方法里,處理鏈接斷開(kāi)后的會(huì)話清除操作。

          13、技術(shù)關(guān)鍵點(diǎn)3:ping、pong的作用

          當(dāng)Client與NettyServer建立鏈接后,由于雙端網(wǎng)絡(luò)較差,Client與NettyServer斷開(kāi)鏈接后,如果NettyServer沒(méi)有感知到,也就沒(méi)有清除SessionMap和Redis中的數(shù)據(jù),這將會(huì)造成嚴(yán)重的問(wèn)題(對(duì)于服務(wù)端來(lái)說(shuō),這個(gè)Client的會(huì)話實(shí)際處于“假死”狀態(tài),消息是無(wú)法實(shí)時(shí)發(fā)送過(guò)去的)。

          此時(shí)就需要一種ping/pong機(jī)制(也就是心跳機(jī)制啦)。

          實(shí)現(xiàn)原理就是:通過(guò)定時(shí)任務(wù),Client每隔一段時(shí)間給NettyServer發(fā)一個(gè)ping消息,NettyServer收到ping消息后給客戶端回復(fù)一個(gè)pong消息,確??蛻舳撕头?wù)端能一直保持鏈接狀態(tài)。如果Client與NettyServer斷連了,NettyServer可以立即發(fā)現(xiàn)并清空會(huì)話數(shù)據(jù)。Netty中的我們可以在Pipeline中添加IdleStateHandler,可達(dá)到這樣的目的。

          如果你不明白心跳的作用,務(wù)必讀以下文章:

          1. 為何基于TCP協(xié)議的移動(dòng)端IM仍然需要心跳保活機(jī)制?
          2. 一文讀懂即時(shí)通訊應(yīng)用中的網(wǎng)絡(luò)心跳包機(jī)制:作用、原理、實(shí)現(xiàn)思路等

          也可以學(xué)習(xí)一下主流IM的心跳邏輯:

          1. 微信團(tuán)隊(duì)原創(chuàng)分享:Android版微信后臺(tái)保活實(shí)戰(zhàn)分享(進(jìn)程保活篇)
          2. 微信團(tuán)隊(duì)原創(chuàng)分享:Android版微信后臺(tái)保活實(shí)戰(zhàn)分享(網(wǎng)絡(luò)保活篇)
          3. 移動(dòng)端IM實(shí)踐:實(shí)現(xiàn)Android版微信的智能心跳機(jī)制
          4. 移動(dòng)端IM實(shí)踐:WhatsApp、Line、微信的心跳策略分析

          如果覺(jué)得理論不夠直觀,下面的代碼實(shí)例可以直觀地進(jìn)行學(xué)習(xí):

          1. 正確理解IM長(zhǎng)連接的心跳及重連機(jī)制,并動(dòng)手實(shí)現(xiàn)(有完整IM源碼)
          2. 一種Android端IM智能心跳算法的設(shè)計(jì)與實(shí)現(xiàn)探討(含樣例代碼)
          3. 自已開(kāi)發(fā)IM有那么難嗎?手把手教你自擼一個(gè)Andriod版簡(jiǎn)易IM (有源碼)
          4. 手把手教你用Netty實(shí)現(xiàn)網(wǎng)絡(luò)通信程序的心跳機(jī)制、斷線重連機(jī)制

          其實(shí),心跳算法的實(shí)際效果,還是有一些邏輯技巧的,以下兩篇建議必讀:

          1. Web端即時(shí)通訊實(shí)踐干貨:如何讓你的WebSocket斷網(wǎng)重連更快速?
          2. 融云技術(shù)分享:融云安卓端IM產(chǎn)品的網(wǎng)絡(luò)鏈路?;罴夹g(shù)實(shí)踐

          14、技術(shù)關(guān)鍵點(diǎn)4:為Server和Client添加Hook

          如果NettyServer重啟了或者進(jìn)程被kill掉,我們需要清除當(dāng)前節(jié)點(diǎn)的SessionMap(其實(shí)不用清理SessionMap,數(shù)據(jù)在內(nèi)存里重啟會(huì)自動(dòng)刪除的)和Redis保存的Client的鏈接信息。

          我們需要遍歷SessionMap找出所有的uid,然后一一清除Redis的數(shù)據(jù),然后優(yōu)雅退出。此時(shí),我們就需要為我們的NettyServer添加一個(gè)Hook,來(lái)做數(shù)據(jù)清理。

          15、技術(shù)關(guān)鍵點(diǎn)5:對(duì)方不在線該如何處理消息?

          Client1給對(duì)方發(fā)消息,我們通過(guò)SessionMap或Redis拿不到對(duì)方的會(huì)話數(shù)據(jù),這就表明對(duì)方不在線。

          此時(shí):我們需要把消息存儲(chǔ)在離線消息表中,當(dāng)對(duì)方下次登錄時(shí),NettyServer查離線消息表,把消息發(fā)給登錄用戶(最好是批量發(fā)送,提高性能)。

          IM中的離線消息處理,也不是個(gè)簡(jiǎn)單的技術(shù)點(diǎn),有興趣可以深入學(xué)習(xí)一下:

          1. IM消息送達(dá)保證機(jī)制實(shí)現(xiàn)(二):保證離線消息的可靠投遞
          2. 阿里IM技術(shù)分享(六):閑魚(yú)億級(jí)IM消息系統(tǒng)的離線推送到達(dá)率優(yōu)化
          3. IM開(kāi)發(fā)干貨分享:我是如何解決大量離線消息導(dǎo)致客戶端卡頓的
          4. IM開(kāi)發(fā)干貨分享:如何優(yōu)雅的實(shí)現(xiàn)大量離線消息的可靠投遞
          5. 喜馬拉雅億級(jí)用戶量的離線消息推送系統(tǒng)架構(gòu)設(shè)計(jì)實(shí)踐

          16、寫(xiě)在最后

          代碼寫(xiě)成這樣,也算是了確了自已手?jǐn)]IM的心愿。唯一遺憾的是,時(shí)間比較緊張,還沒(méi)來(lái)得及實(shí)現(xiàn)消息ack機(jī)制,保證消息一定會(huì)送達(dá),這個(gè)筆者以后會(huì)補(bǔ)充上去的。

          好了,這就是我開(kāi)發(fā)的這個(gè)簡(jiǎn)易的聊天系統(tǒng),麻雀雖小,五臟俱全,大家有什么不明白的地方,可以直接在下方留言,筆者會(huì)一一回復(fù)的,謝謝大家。

          17、系列文章

          18、參考資料

          [1] 新手入門(mén):目前為止最透徹的的Netty高性能原理和框架架構(gòu)解析

          [2] 寫(xiě)給初學(xué)者:Java高性能NIO框架Netty的學(xué)習(xí)方法和進(jìn)階策略

          [3] 史上最強(qiáng)Java NIO入門(mén):擔(dān)心從入門(mén)到放棄的,請(qǐng)讀這篇!

          [4] Java的BIO和NIO很難懂?用代碼實(shí)踐給你看,再不懂我轉(zhuǎn)行!

          [5] 史上最通俗Netty框架入門(mén)長(zhǎng)文:基本介紹、環(huán)境搭建、動(dòng)手實(shí)戰(zhàn)

          [6] 理論聯(lián)系實(shí)際:一套典型的IM通信協(xié)議設(shè)計(jì)詳解

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

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

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

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

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

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

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

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

          [15] 基于實(shí)踐:一套百萬(wàn)消息量小規(guī)模IM系統(tǒng)技術(shù)要點(diǎn)總結(jié)

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



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


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


          網(wǎng)站導(dǎo)航:
           
          Jack Jiang的 Mail: jb2011@163.com, 聯(lián)系QQ: 413980957, 微信: hellojackjiang
          主站蜘蛛池模板: 资中县| 车险| 麦盖提县| 鄂托克前旗| 天柱县| 三台县| 岱山县| 永昌县| 丽水市| 莱阳市| 会理县| 陇川县| 通州区| 大厂| 巴林右旗| 翁牛特旗| 玉环县| 修水县| 沭阳县| 商河县| 深泽县| 吴江市| 阳高县| 襄汾县| 同仁县| 峨眉山市| 岳阳县| 敦化市| 三江| 信宜市| 舒城县| 峨眉山市| 郓城县| 澎湖县| 新郑市| 贺州市| 明星| 凌源市| 桦甸市| 勃利县| 开原市|