1、業務處理流程
1.1 主從模型
1.2 Debug跟蹤
我們用Netty源碼包下面的example來Debug觀察一下,包路徑io.netty.example.echo
- NioEventLoop#processSelectedKeysOptimized()方式循環處理不同的事件。如下圖。
- NioEventLoop#processSelectedKey方法處理一個事件,在該方法中的unsafe.read()這一行打斷點(如1.2圖), 這是NioEventLoop線程處理讀(READ)事件和接受連接(ACCEPT)事件的代碼。
- 啓動Server,Client發起請求。
1.3 BossGroup處理連接事件,第一次進入是ACCEPT事件
如圖, 此時線程是nioEventLoopGroup-2-1,這是BossGroup,就是1.1圖中的MainReactor。
unsafe類型AbstractNioMessageChannel.NioMessageUnsafe,這是處理連接事件的,入參ch(channel)類型是NioServerSocketChannel
1.4 跳過這一次循環,進入下一次循環,這次是READ事件
如圖, 此時線程是nioEventLoopGroup-3-1,這是workerGroup,即是1.1圖中的subReactor
unsafe類型AbstractNioByteChannel.NioByteUnsafe#read,這是處理讀事件的,入參ch(channel)類型是NioSocketChannel
1.5 進入unsafe.read
這裏是讀取數據的邏輯,這個方法主要邏輯前面已經分析了,見Netty源碼-業務流程之讀事件
這裏我們重點關注第4步,pipeline.fireChannelRead(byteBuf); 這裏會轉到我們自定義的handler處理數據。
pipeline是責任鏈模式
看一下Debug信息,如下圖,pipeline有四個handler,通過雙鏈表連接在一起,HeadContext和TailContext分別表示責任鏈的頭和尾,第三個是我自定義的EchoServerHandler的,真個責任鏈將會被依次執行。
1.6 進入pipeline.fireCHannelRead,我們來到AbstractChannelHandlerContext#fireChannelRead
findContextInbound找到一個責任節點(Inbound類型)執行,MASK_CHANNEL_READ是channel read掩碼。
MASK_ONLY_INBOUND(下圖2)表示所有Inbound事件掩碼集合,MASK_CHANNEL_READ和MASK_ONLY_INBOUND與運算結果不是0,就表示執行channelRead事件
1.7 最終會進入自定義Handler
最終達到我們自定義的channelRead邏輯,這裏可以寫我們自己的業務邏輯