基於Netty的Android系統IM簡單實現原理
最近在開發MobIM,實現了消息傳輸和群等功能的IM功能。SDK功能包小,而功能全面。可以與原來的系統進行無縫整合。
自己抽空也實現了一套IM Server和IMClient的業務通信模式。沒有實現複雜的UI界面,實現簡單的登錄註冊,發消息,收消息。伺服器端與客戶端都使用Netty通信。
Netty基於非阻塞(nio),事件驅動的網路應用程序框架和工具。
通過Netty面對大規模的並發請求可以處理的得心用手。用來替代原來的bio網路應用請求框架。
BIO通信即平時使用的基於Socket,ServerSocket的InputStream和OutStream。
Netty神奇的地方在於是否是阻塞的。
在BIO模型中,伺服器通過ServerSocket來開啟監聽,每當有請求的時候開啟一個線程來接受處理和維持狀態。這種思想在低並發,小吞吐的應用還可以應付,一旦遇到大並發,大吞吐的請求,必然歇菜。線程和客戶端保持著1:1的對應關係,維持著線程。維持那麼的多的線程,JVM必然不堪重負,伺服器必然崩潰,宕機。
而在非阻塞的Netty中,卻可以應付自如。從容應對。Tomcat就是基於BIO的網路通信模式(Tomcat可以通過一定配置,改成非阻塞模式),而JBoss卻是基於非阻塞的NIO實現。
NIO的網路通信模式很強勁,但是上手卻一點都不容易。其中解決和牽扯到好多網路問題。如:網路延時,TCP的粘包/拆包,網路故障等一堆一堆的問題。
而Netty呢,針對nio複雜的編程難題而進行一系列的封裝實現,提供給廣大開發者一套開源簡單,方便使用的API類庫,甚至青出於藍而勝於藍,甚至幾乎完美的解決CPU突然飆升到100%的bug :
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6403933
其實也沒有真正的解決,只是把復現的概率降到了最低而已。
用Netty來實現IM實在太合適了。可以在最短的時間裡整出一套思路清晰,架構簡明的IM通信底層模型。提下需求,底層用JSON 字元串String進行通信,對象通過JSON序列化成JSON String。收到JSON數據後再反序列化成對象。
首先,我們先看伺服器是怎麼實現的。
以上是Netty伺服器啟動的代碼。其中需要注意childHandler方法。需要把我們要添加的業務處理handler來添加到這裡。
通過ChannelPipeline 添加ChannelHandler。而處理字元串的就在IMServerHandle里實現。IMServerHandle繼承了SimpleChannelInboundHandler類。
其中泛型T就是要轉換成的對象。客戶端與伺服器端通信是本質上通過位元組碼byte[]通信的,而通過StringDecoder 和StringEncoder工具類對byte[]進行轉換,在IMServerHandle中獲取到String進行處理即可。
看下IMServerHandle的實現方式。
通過IMServerHandle可以十分方便的處理獲取到的String字元串。處理完後,可以直接通過ChannelHandlerContext的writeAndFlush方法發送數據。
再看下Netty客戶端如何實現。
Netty的client端實現和Server實現方式大同小異。比Server端要簡要些了。少一個NIOEventLoop。在Bootstrap 的handle方法中增加ChannelInitializer初始化監聽器,並增加了IMClientHandler的監聽操作。其中IMClientHandler具體處理伺服器返回的通信信息。
通過ChannelFuture 獲取Channel,通過Channel在一個循環里發送請求。如果消息隊列BlockingQueue非空的時候,獲取Request並發送。以上發送,如何接受數據呢?接受到的json被反序列化直接變成了對象Response,對Response進行處理即可。
定義了一個消息接受到的監聽介面。
在介面onMessageReceived方法里直接對獲取成功的響應進行處理。
而伺服器端對某個客戶端進行發送操作,把Channel添加到ChannelGroup里,將uname和channelid對應起來。需要對某個用戶發送消息的時候通過uname獲取channelid,通過channelid從ChannelGroup里獲取channel,通過channel發送即可。
具體操作如下:
通過以上代碼解析應該對IM的通信模式有了比較全面的認識。具體實現過程可以下載源代碼進行查看:
https://github.com/sinxiao/NettyIMServerAndAndroidClient
歡迎大家反饋提出問題。
運行效果圖
文/ Mob 徐化傑
TAG:Mob開發者服務平台 |