《Netty 權威指南》—— 服務端序列圖
宣告:本文是《Netty 權威指南》的樣章,感謝博文視點授權併發程式設計網站釋出樣章,
下面,我們對NIO服務端的主要建立過程進行講解和說明,作為NIO的基礎入門,我們將忽略掉一些在生產環境中部署所需要的一些特性和功能。
步驟一:開啟ServerSocketChannel,用於監聽客戶端的連線,它是所有客戶端連線的父管道,程式碼示例如下:
ServerSocketChannel acceptorSvr = ServerSocketChannel.open();
步驟二:繫結監聽埠,設定連線為非阻塞模式,示例程式碼如下:
acceptorSvr.socket().bind(new InetSocketAddress(InetAddress.getByName(“IP”), port)); acceptorSvr.configureBlocking(false);
步驟三:建立Reactor執行緒,建立多路複用器並啟動執行緒,程式碼如下:
Selector selector = Selector.open(); New Thread(new ReactorTask()).start();
步驟四:將ServerSocketChannel註冊到Reactor執行緒的多路複用器Selector上,監聽ACCEPT事件,程式碼如下:
SelectionKey key = acceptorSvr.register( selector, SelectionKey.OP_ACCEPT, ioHandler);
步驟五:多路複用器線上程run方法的無限迴圈體內輪詢準備就緒的Key,程式碼如下:
int num = selector.select(); Set selectedKeys = selector.selectedKeys(); Iterator it = selectedKeys.iterator(); while (it.hasNext()) { SelectionKey key = (SelectionKey)it.next(); // ... deal with I/O event ... }
步驟六:多路複用器監聽到有新的客戶端接入,處理新的接入請求,完成TCP三次握手,建立物理鏈路,程式碼示例如下:
SocketChannel channel = svrChannel.accept();
步驟七:設定客戶端鏈路為非阻塞模式,示例程式碼如下:
channel.configureBlocking(false); channel.socket().setReuseAddress(true);
步驟八:將新接入的客戶端連線註冊到Reactor執行緒的多路複用器上,監聽讀操作,用來讀取客戶端傳送的網路訊息,程式碼如下:
SelectionKey key = socketChannel.register( selector, SelectionKey.OP_READ, ioHandler);
步驟九:非同步讀取客戶端請求訊息到緩衝區,示例程式碼如下:
int readNumber = channel.read(receivedBuffer);
步驟十:對ByteBuffer進行編解碼,如果有半包訊息指標reset,繼續讀取後續的報文,將解碼成功的訊息封裝成Task,投遞到業務執行緒池中,進行業務邏輯編排,示例程式碼如下:
Object message = null; while(buffer.hasRemain()) { byteBuffer.mark(); Object message = decode(byteBuffer); if (message == null) { byteBuffer.reset(); break; } messageList.add(message ); } if (!byteBuffer.hasRemain()) byteBuffer.clear(); else byteBuffer.compact(); if (messageList != null & !messageList.isEmpty()) { for(Object messageE : messageList) handlerTask(messageE); }
步驟十一:將POJO物件encode成ByteBuffer,呼叫SocketChannel的非同步write介面,將訊息非同步傳送給客戶端,示例程式碼如下:
socketChannel.write(buffer);
注意:如果傳送區TCP緩衝區滿,會導致寫半包,此時,需要註冊監聽寫操作位,迴圈寫,直到整包訊息寫入TCP緩衝區,此處不贅述,後續Netty原始碼分析章節會詳細分析Netty的處理策略。
當我們瞭解建立NIO服務端的基本步驟之後,下面我們將前面的時間伺服器程式通過NIO重寫一遍,讓大家能夠學習到完整版的NIO服務端建立。