前言
本文主要梳理Netty用戶端如何發起連接配接請求的以及最終通過SocketChannel與服務端建立連接配接,順便分析了在此過程中涉及到的位址解析過程。
一、擷取位址解析器
備注:在Netty用戶端發起連接配接前,先擷取了AddressResolver,并進行了解析判斷。
擷取AddressResolver過程
備注:建立AddressResolver并将其放到緩存Map中,key為executor。
備注:預設使用DefaultAddressResolverGroup中的DefaultNameResolver建構InetSocketAddressResolver。
小結:從上面擷取位址解析過程中,AddressResolverGroup擁有一組AddressResolver存儲于Map中,key為EventExecutor,而AddressResolver是通過NameResolver建構的。
二、位址解析器圖譜
1.AddressResolverGroup類圖
2.AddressResolver類圖
3.NameResolver類圖
4.關系圖示
三、位址解析過程
位址解析通過下面的方法來實作。分别看下isSupported、isResolved、doResolve的邏輯。
@1 isSupported主要判斷傳入socket位址是否屬于InetSocketAddress,通過JDK中isInstance來實作。
@2 doIsResolved判斷包含了isSupported和非空判斷,入參非空并且屬于InetSocketAddress則标記解析成功
@3 doResolve 根據host name解析成InetSocketAddress,通過InetAddress.getByName(hostname)實作。
小結:位址解析主要得到SocketAddress是合法有效的,如果為host name預設為通過InetAddress.getByName轉換為InetAddress。
四、建立連接配接
在位址解析成功後,該建立連接配接了,接下來看下netty是如何發起的。
備注:接着調用AbstractChannel的connect方法,即:DefaultChannelPipeline#connect。
備注:從連結清單的最後一個tail發起連接配接。
備注:從之前文章分析中,我們知道連結清單構成。會調用到AbstractChannelHandlerContext#connect方法。通過方法findContextOutbound查找連結清單中負責出站的HandlerContext調用其connect方法,結束後向下一個出站HandlerContext傳遞調用。
備注:出站HandlerContext查找過程。
備注:上圖為運作時DefaultChannelPipeline連結清單中的Handler結構。尾部為TailContext,頭部為HeadContext。
備注:繼續上面的連接配接傳遞,最後會調用HeaderContext的connect方法。通過unsafe.connect向服務端發起連接配接調用。
備注:調用NioSocketChannel#doConnect方法,最後通過Java NIO的SocketChannel#connect發起連接配接請求。
作者丨梁勇
來源丨瓜農老梁(ID:gh_01130ae30a83)