Netty新連接接入
問題
1.Netty是在哪裏檢測有新連接接入的?
答:boss線程的第一個過程輪訓處Accept事件,然後boss線程第二個過程通過jdk底層的channel的accept方法創建該連接。
2.新連接是怎樣註冊到NioEventLoop線程的?
答:新連接NioEventLoop的分配和selector註冊可以回答。boss線程調用chooser的next方法,拿到一個NioEventLoop,然後將這條連接註冊到NioEventLoop的selector上面。
Netty新連接接入處理邏輯
(1)檢測新連接:新連接通過服務端Channel綁定的Selector輪詢出Accept事件
(2)創建NioSocketChannel:基於jdkNio的channle創建出一個netty的NioSocketChannel,也就是客戶端Channel
(3)分配線程及註冊selector:netty給客戶端Channel分配一個NioEventLoop,並且把這條Channel註冊到該NioEventLoop對應的selector上,至此這條Channel後續的讀寫都由此NioEventLoop進行管理
(4)向selector註冊讀事件:註冊的過程和服務端啟動註冊事件復用同一段邏輯。
(1)檢測新連接
processSelectedKey(key,channel)[入口]:添加斷點
NioMessageUnsafe.read()
doReadMessages()[while循環]
javaChannel().accept()
- 運行Server.java的main函數,啟動服務端
- 在terminal中輸入 telnet 127.0.0.1 8888(如果出現telnet不是內部或外部命令...則在控制面板-程序-啟用或關閉Windows功能,勾選Telnet客戶端)
- 一步一步斷點調試
(2)創建NioSocketChannel
new NioSocketChannel(parent,ch)[入口]
AbstractNioByteChannel(p,ch,op-read)
configureBlocking(false)&save op
create id,unsafe,pipeline
new NioSocketChannelConfig()
setTcpNoDelay(true)禁止Nagle算法,小的數據包會發出去,降低延遲
(3)分配線程及註冊selector
服務端Channel的pipeline構成
Head—>ServerBootstrapAcceptor—>Tail
其中ServerBootstrapAcceptor做以下事情:
- 添加childHandler
- 設置options和attrs
- 選擇NioEventLoop並註冊selector
(4)向selector註冊讀事件
Netty中Channel的分類
- NioServerSocketChannel:服務端Channel
- NioSocketChannel:客戶端Channel
- Unsafe
服務端Channel和客戶端Channel的不同點:
(a) 客戶端Channel(AbstractNioByteChannel)向AbstractNioChannel註冊一個讀事件
服務端Channel(AbstractNioMessageChannel)向AbstractNioChannel註冊一個accept事件
服務端Channel和客戶端Channel共同的部分都由AbstractNioChannel實現
(b) 這兩種Channel底層對應的Unsafe不同
客戶端Channel對應NioByteUnsafe:讀取IO數據
服務端Channel對應NioMessageUnsafe:讀一條連接
Netty新連接接入