天天看點

Netty之用戶端連接配接調用

前言

本文主要梳理Netty用戶端如何發起連接配接請求的以及最終通過SocketChannel與服務端建立連接配接,順便分析了在此過程中涉及到的位址解析過程。

一、擷取位址解析器

Netty之用戶端連接配接調用

備注:在Netty用戶端發起連接配接前,先擷取了AddressResolver,并進行了解析判斷。

擷取AddressResolver過程

Netty之用戶端連接配接調用

備注:建立AddressResolver并将其放到緩存Map中,key為executor。

Netty之用戶端連接配接調用
Netty之用戶端連接配接調用

備注:預設使用DefaultAddressResolverGroup中的DefaultNameResolver建構InetSocketAddressResolver。

小結:從上面擷取位址解析過程中,AddressResolverGroup擁有一組AddressResolver存儲于Map中,key為EventExecutor,而AddressResolver是通過NameResolver建構的。

二、位址解析器圖譜

1.AddressResolverGroup類圖

Netty之用戶端連接配接調用

2.AddressResolver類圖

Netty之用戶端連接配接調用

3.NameResolver類圖

Netty之用戶端連接配接調用

4.關系圖示

Netty之用戶端連接配接調用

三、位址解析過程

位址解析通過下面的方法來實作。分别看下isSupported、isResolved、doResolve的邏輯。

Netty之用戶端連接配接調用
Netty之用戶端連接配接調用

@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是如何發起的。

Netty之用戶端連接配接調用
Netty之用戶端連接配接調用

備注:接着調用AbstractChannel的connect方法,即:DefaultChannelPipeline#connect。

Netty之用戶端連接配接調用

備注:從連結清單的最後一個tail發起連接配接。

Netty之用戶端連接配接調用

備注:從之前文章分析中,我們知道連結清單構成。會調用到AbstractChannelHandlerContext#connect方法。通過方法findContextOutbound查找連結清單中負責出站的HandlerContext調用其connect方法,結束後向下一個出站HandlerContext傳遞調用。

Netty之用戶端連接配接調用

備注:出站HandlerContext查找過程。

Netty之用戶端連接配接調用

備注:上圖為運作時DefaultChannelPipeline連結清單中的Handler結構。尾部為TailContext,頭部為HeadContext。

Netty之用戶端連接配接調用

備注:繼續上面的連接配接傳遞,最後會調用HeaderContext的connect方法。通過unsafe.connect向服務端發起連接配接調用。

Netty之用戶端連接配接調用
Netty之用戶端連接配接調用

備注:調用NioSocketChannel#doConnect方法,最後通過Java NIO的SocketChannel#connect發起連接配接請求。

作者丨梁勇

來源丨瓜農老梁(ID:gh_01130ae30a83)