文章目錄
- Client
- Server
- model-1
- model-2
- model-3
- model-netty
- interestOps, selectionKey
- upstream:
- downstream:
- to be continued…
demo樣本Client
Server
Nio模型model-1
model-2
model-3
model-netty
Boss
Worker
Channel設計
情境
connect->read->write->close
interestOps, selectionKey
OP_READ可讀可寫. neither read nor write operation has been suspended.
OP_WRITE不可讀不可寫. both has been suspended.
OP_READ_WRITE 可讀不可寫. write operation has been suspended.
OP_NONE 不可讀可寫. read operation has been suspended.
Pipeline設計upstream:
l HutuDecoder
l messageReceived, exceptionCaught, channelOpen, channelClosed, channelBound, channelUnbound, channelConnected, writeComplte, channelDisconnected, changeInterestChanged
downstream:
l HutuEncoder
l write, bind, unbind, connect, disconnect, close
ByteBuffer設計to be continued…
網摘:分析Netty工作流程
下面以Netty中Echo的例子進行流程跟蹤,並簡要的
伺服器啟動->用戶端串連-> 伺服器處理串連-> 伺服器處理用戶端資料<-> 用戶端處理伺服器資料
1:用戶端串連:
我們直接看這行代碼:
bootstrap.connect(new InetSocketAddress(host, port));
通過協助類ClientBootstrap來串連伺服器。
Debug源碼進去發現最後是某個Channel類進行connect操作。
而這個Channel是如何來的呢?其實是從前面的 ChannelFactory和ChannelPipelineFactory得到的。
Channel.connect-> AbstractChannel.connect->Channels.connect(…);
Channels是Channel的協助類,封裝一些常用的操作。在封裝操作時,基本都是觸發事件。
這裡發起一個connectd的Downstream的事件。
所有的事件都是丟給ChannelPipeline進行管理,ChannelPipeline使用了責任鏈模式來將事件傳送給註冊到Pipeline中的ChannelHandler,由ChannelHandler進行處理。如果遍曆了所有的ChannelHandler後則交給ChannelSink進行處理,ChannelSink根據不同的事件進行不同的處理,對於connect事件,ChannelSink發送串連操作後則將該Channel註冊到NioWorker中,以後的任何事件都通過NioWorker(封裝selector的操作)來進行處理。
用戶端串連的流程為:
ClientBootstrap.connect –>Channel.connect->
AbstractChannel.connect->Channels.connect(…)
-> 發送connect事件-> ChannelSink->發起實際的串連操作->將Channel註冊給Nioworker
2:伺服器啟動:
bootstrap.bind(…)-> 觸發ServerSocketChannel.open()的事件
->捕捉open事件,channel.bind-> Channels.bind(…) -> 發起bind命令-> PipelineSink進行處理-> 使用socket進行bind,等待串連事件。
3: 伺服器處理串連:
伺服器啟動後,NioServerSocketPipelineSink.Boss.run()在監聽accept事件-> 捕捉到accept事件 -> 將NioWorker進行註冊NioSocketChannel
-> 向java.nio.SocketChannel註冊op_read的監聽。
4:用戶端開始向伺服器發送資料:
當用戶端串連Server後,就會發起Connected的upstream事件->通過Pipeline進行處理-> SimpleChannelUpstreamHandler.handleUpstream()->
EchoClientHandler.channelConnected()
5:伺服器端接收並處理資料
接收資料:
NioWorker.run()->nioworker. processSelectedKeys()->
Nioworker. Read()將從SocketChannel讀取的資料封裝成
ChannelBuffer ->發送upstream事件:fireMessageReceived(channel,buffer) –> 由註冊到Pipeline中的Hanlder進行處理: EchoServerHandler. messageReceived(…)
發送資料:
e.getChannel().write(e.getMessage());->Channels.write()->
發起downstream事件-> NioServerSocketPipelineSink. handleAcceptedSocket()將向外寫的事件放入Channel中,然後通過NioWorker.writeFromUserCode()進行發送。
6:用戶端:用戶端的流程和伺服器端類似。
總結:
1: Netty將操作封裝成事件,比如: 發起串連時,產生connect的downstream事件。串連完畢後,產生upstream的connect事件。
2:所有的事件都是放入Pipeline進行傳送,傳送的過程中可能被註冊到pipeline中的Handler進行處理
3:在Pipeline傳送完後,都必須都通ChannelSink進行處理。Sink預設處理了瑣碎的操作,必須串連、讀寫等等。
4:Channels:幾乎所有的操作都能在這裡找到,當然Channels一般是發送事件
5:NioWorker: 處理IO事件的核心類,並承擔了分發的責任。