天天看點

HttpAsyncClient的連接配接池使用

代碼示例

流程分析

簡要流程總結如下:

httpasyncclient有一個abstractmultiworkerioreactor和abstractioreactor,

前者和後者類似于netty的bossgroup和workergroup, abstractmultiworkerioreactor負責channel的連接配接, abstractioreactor負責channel的讀寫

先要明白連接配接池的結構

abstractnioconnpool 下各個變量的含義

1. 發起請求

 a. 根據請求route檢視連接配接池, 如果連接配接池不為空, 直接傳回跟池中connection綁定的future,

并把該conn放入leased清單

 b. 如果因為某些原因導緻目前請求無法取得連接配接, 但是沒有發生緻命錯誤的, 請求将被放入一個 leasing 清單,

這個清單會在後續動作中被取出來做連接配接重試

 c. 如果實在連接配接過程中出現了移除等不可恢複的錯誤, 則将request标記為completed, 退出方法後調用firecallback,

進行回調清理, 這次請求就算是失敗結束了

 d. 如果是因為連接配接池沒有可用連接配接, 但是可以建立連接配接的情況, 則會将request 加入pending清單, 并調用

selector的wakeup()方法,

selector在wakeup以後會使用abstractmultiworkerioreactor(bossgroup)來進行連接配接操作,

并注冊到selector中, 後續的connectable事件監聽和channel連接配接成功注冊也是由他完成的

2. abstractioreactor監聽讀寫事件

3. 通過decoder檢測response已經完成, 最後将連接配接release到連接配接池中, 此時将連接配接從leased清單除去,

并加入到available中

調用

請求開始, 裡面會調用 execute(request, new basichttpcontext(), callback)

context 代表了一次請求的上下文, 裡面實際上就是一個用來存儲 attribute 的結構, 預設的實作 basichttpcontext

實際上就是一個 concurrenthashmap

context 是可以嵌套的, 代碼如下

接着看執行流程

這裡會通過原來的請求資訊生成一個requestproducer跟responseconsumer,

預設會調用httpasyncclient的internalhttpasyncclient的實作, 如下

 這裡通過生成一個exchangehandler來實作請求開始, 檢視 handler.start()

 接着往下

再看nhttpclientconnectionmanager下的

它調用了poolingnhttpclientconnectionmanager的實作

看 abstractnioconnpool 的 lease 方法

這裡主要涉及到連接配接池 abstractnioconnpool

以及連接配接池下得實際存儲連接配接的 routespecificpool, 

然後開始分析連接配接流程

看看defaultconnectingioreactor的connect方法

在abstractmultiworkerioreactor中有一個execute()方法

首次連接配接的時候, 觸發的是 defaultconnectingioreactor 的 processevents 方法

接下來看連接配接成功後的ioreactor如何處理, 如下 baseioreactor 的 execute 方法

這個就跟abstractmultiworkerioreactor類似, 隻不過兩個人的興趣集事件不太一樣, 看看 abstractioreactor

的實作類 baseioreactor就知道了

它實際上隻會處理 read 跟 write 事件

這裡特别注意一下 abstractnioconnpool requestcomplete 并不是整個請求結束, 而是連接配接成功的意思,

看看他的調用的地方和觸發的東西

最開始他是從 abstractioreactor 的processnewchannels中來的, 這個方法在execute裡被觸發

看看連接配接池 abstractnioconnpool 的completed 方法做了什麼

主要做的事情就是設定了一下連接配接的sotimeout, 還有就是将連接配接從 pending清單移到了 lease 集合

最後, 來看看 連接配接是如何歸還的

通過對abstractnioconnpool的release方法的跟蹤, 最後找了還是在 baseioreactor 監聽到 readable

時間的時候, 調用了httpasyncrequestexecutor的inputready

方法

當檢測到response已經完了, 就會進入complete流程, 最後回到releaseconnection流程,

最後到達連接配接池的release