(二)
Netty源碼分析:
做一套rpc長連接框架,架構上其實沒有多么難,只要具體里面的步驟包括即可:
一、全雙工的socket連接;
二、心跳檢測
三、超時重連、重傳
四、白名單
五、編解碼
這里還有相當多的技術規范與技術點,比如tcp消息封裝定義消息頭、消息體;定義反射類與方法用於遠程方法執行;主從線程與線程池的設定;編解碼序列的定義;粘包、拆
包,涉及到tcp報文包的分片;網絡的流量、擁塞控制;編解碼中的大小端;buffer數據解析等。
其實,我不得不吐槽一下,netty源碼分析那本書有些地方並不好,有些地方沒有按照思維邏輯去講解,而是按照執行順序,這樣其實並不符合這么一個項目的構建過程!
還有一點,講太細致,太深入,如果要全部分析完成,恐怕會非常耗時,其實很多只需要整體把握,如果有時間再慢慢消化!
全雙工連接:
對於java來說,原生的java nio,其存在固有的復雜性與bug,難以令人滿意!而netty則將用戶邊界做了封裝,降低用戶的開發難度,實際上我對於netty這本書的講解流程並不滿
意,因為它是按照代碼的執行順序講解的,實際上並不符合人的思維邏輯;接下來我將會先從書中將的內容順序梳理,然后再通過思維流程進行梳理一遍。
首先要通過epoll理解buffer與channal!這兩者是不同的,channal從物理上將是位於機器的內核空間,處於一個接收網絡數據、本地文件數據等一系列前置底層的數據操作!
而buffer則不然,對於java來說,就是為了將這些數據進行結構化,同時在物理上講這是一種位於用戶空間,也就是java進程中為了與對應java基本數據類型等的映射!
Server端:
一、根據netty權威指南,ServerBootstrap是socket服務端的啟動輔助類,用途是封裝啟動參數;
二、使用綁定Reactor線程池,處理多路復用的管道channal (netty書上說使用EventLoopGroup,但是我沒有找到對應類的源碼,可能讀的不夠深吧),也就是連接;
三、使用ServerSocketChannel嫁接數據 =》處理活躍連接的管道上,處理活躍連接;
四、ChannalPipeline這一步應該並不歸於建立連接!用於處理請求數據的,比如驗證信息、編碼解碼、心跳檢測、流量控制等;
五、綁定監聽端口,ServerSocketChannal注冊到Selector(多路復用器,也就是為了處理epoll中的epoll_wait活躍事件)
六、輪詢Selector,找出對應的Channal;
最終建立連接會有一個listen方法傳入文件描述符、backlog,具體的實現類方法可以看
這個類,會發現一個這樣的方法
最終調用native的c函數獲取操作系統的描述符,建立連接。關於backlog這個參數
是內核為此套接字排隊的最大連接的個數。
然后關於建立連接使用的兩個隊列:未連接隊列、已連接隊列,就是涉及到tcp的相關知識了!如果是建立連接的時候客戶端發送syn報文段,此時未連接隊列創建一個節點,當
server端發送syn與ack報文段之后一直到server端收到client端的ack報文段之前一直處於未連接隊列;如果server端收到client的第三次握手ack,則將未連接隊列的此節點移動到已完
成連接隊列的隊尾。系統默認為5,一般都會進行設置用以支持高並發!
正是因為不同的操作方式,所以有了不同的操作位!SelectionKey,中有四個常量分別為OP_READ、OP_WRITE、OP_ACCEPT、OP_CONNECT,用於表示不同的事件。這
樣切合了事件機制。這四種常量分別為針對1的位操作,分別為1、4、8、16,對應二進制位為0001、0100、1000、10000;書上指定是說錯了的!使用位操作的優勢,說是方便網
絡操作位狀態的判斷與修改,這我可以理解,因為如果都轉成二進制的話,在數據結構上更方便轉換,但是我不理解的是為什么不適用0001、0010、0100、1000呢?后續再考量這
到底是怎么回事!
基本上整體思路就是這樣,具體到內部還有很多相關於java的內容,比如為什么ChannalHanlder使用volatile?Volatile只保證了可見性,沒有保證原子性,我也沒有找到它需要
保證原子性的操作,那么是它不需要保證原子性還是再更深處的地方做了處理?
Client端:
終於到了client端了!關於這塊暫時不具體考慮netty的實現,而且不再按照書上說的代碼執行順序講,具體的后續補發!
一、建立雙工連接,可以使用NioSocketChannal、SocketChannal;
二、根據tcp的三次握手報文段,確認SelectionKey的枚舉類型;
三、如果進入ChannalActive階段,也就是epoll中epoll_waite活躍的連接,則設置網絡操作位為SelectionKey.OP_READ階段,否則連接到selector(多路復用器)階段;
==========================================================================================================================
篇章二 - 定義request、response
篇章三 - 超時重傳、心跳檢測
篇章四 - 負載均衡
篇章五 - 服務平台管理