httpclient ConnectionHolder連接池連接保持源碼解析
序
本文主要研究一下httpclient的ConnectionHolder
ConnectionReleaseTrigger
org/apache/http/conn/ConnectionReleaseTrigger.java
/** * Interface for releasing a connection. This can be implemented by various * "trigger" objects which are associated with a connection, for example * a {@link EofSensorInputStream} or the {@link ManagedHttpClientConnection} itself. * <p> * The methods in this interface can safely be called multiple times. * The first invocation releases the connection, subsequent calls * are ignored. * * @since 4.0 */ public interface ConnectionReleaseTrigger { /** * Releases the connection with the option of keep-alive. This is a * "graceful" release and may cause IO operations for consuming the * remainder of a response entity. Use * {@link #abortConnection abortConnection} for a hard release. The * connection may be reused as specified by the duration. * * @throws IOException * in case of an IO problem. The connection will be released * anyway. */ void releaseConnection() throws IOException; /** * Releases the connection without the option of keep-alive. * This is a "hard" release that implies a shutdown of the connection. * Use {@link #releaseConnection()} for a graceful release. * * @throws IOException in case of an IO problem. * The connection will be released anyway. */ void abortConnection() throws IOException; }
ConnectionReleaseTrigger定義了releaseConnection、abortConnection方法
ConnectionHolder
org/apache/http/impl/execchain/ConnectionHolder.java
@Contract(threading = ThreadingBehavior.SAFE) class ConnectionHolder implements ConnectionReleaseTrigger, Cancellable, Closeable { private final Log log; private final HttpClientConnectionManager manager; private final HttpClientConnection managedConn; private final AtomicBoolean released; private volatile boolean reusable; private volatile Object state; private volatile long validDuration; private volatile TimeUnit timeUnit; public ConnectionHolder( final Log log, final HttpClientConnectionManager manager, final HttpClientConnection managedConn) { super(); this.log = log; this.manager = manager; this.managedConn = managedConn; this.released = new AtomicBoolean(false); } public boolean isReusable() { return this.reusable; } public void markReusable() { this.reusable = true; } public void markNonReusable() { this.reusable = false; } public void setState(final Object state) { this.state = state; } public void setValidFor(final long duration, final TimeUnit timeUnit) { synchronized (this.managedConn) { this.validDuration = duration; this.timeUnit = timeUnit; } } private void releaseConnection(final boolean reusable) { if (this.released.compareAndSet(false, true)) { synchronized (this.managedConn) { if (reusable) { this.manager.releaseConnection(this.managedConn, this.state, this.validDuration, this.timeUnit); } else { try { this.managedConn.close(); log.debug("Connection discarded"); } catch (final IOException ex) { if (this.log.isDebugEnabled()) { this.log.debug(ex.getMessage(), ex); } } finally { this.manager.releaseConnection( this.managedConn, null, 0, TimeUnit.MILLISECONDS); } } } } } @Override public void releaseConnection() { releaseConnection(this.reusable); } @Override public void abortConnection() { if (this.released.compareAndSet(false, true)) { synchronized (this.managedConn) { try { this.managedConn.shutdown(); log.debug("Connection discarded"); } catch (final IOException ex) { if (this.log.isDebugEnabled()) { this.log.debug(ex.getMessage(), ex); } } finally { this.manager.releaseConnection( this.managedConn, null, 0, TimeUnit.MILLISECONDS); } } } } @Override public boolean cancel() { final boolean alreadyReleased = this.released.get(); log.debug("Cancelling request execution"); abortConnection(); return !alreadyReleased; } public boolean isReleased() { return this.released.get(); } @Override public void close() throws IOException { releaseConnection(false); } }
ConnectionHolder實(shí)現(xiàn)了ConnectionReleaseTrigger接口,它提供了isReusable、markReusable、markNonReusable、setValidFor、releaseConnection、abortConnection、cancel、close等方法,其中releaseConnection是依賴reusable屬性來決定是關(guān)閉連接還是歸還連接,而abortConnection方法直接managedConn.shutdown(),然后在執(zhí)行manager.releaseConnection
releaseConnection在連接復(fù)用則執(zhí)行manager.releaseConnection,連接不復(fù)用先執(zhí)行managedConn.close()再執(zhí)行manager.releaseConnection(validDuratioin為0);
abortConnection先執(zhí)行this.managedConn.shutdown(),再執(zhí)行manager.releaseConnection(validDuratioin為0);
close與shutdown的區(qū)別在于close是優(yōu)雅關(guān)閉,會(huì)試圖flush內(nèi)部的output buffer,shutdown是強(qiáng)制關(guān)閉,不會(huì)試圖去flush內(nèi)部的buffer
MainClientExec
org/apache/http/impl/execchain/MainClientExec.java
public CloseableHttpResponse execute( final HttpRoute route, final HttpRequestWrapper request, final HttpClientContext context, final HttpExecutionAware execAware) throws IOException, HttpException { //...... // The connection is in or can be brought to a re-usable state. if (reuseStrategy.keepAlive(response, context)) { // Set the idle duration of this connection final long duration = keepAliveStrategy.getKeepAliveDuration(response, context); if (this.log.isDebugEnabled()) { final String s; if (duration > 0) { s = "for " + duration + " " + TimeUnit.MILLISECONDS; } else { s = "indefinitely"; } this.log.debug("Connection can be kept alive " + s); } connHolder.setValidFor(duration, TimeUnit.MILLISECONDS); connHolder.markReusable(); } else { connHolder.markNonReusable(); } //...... // check for entity, release connection if possible final HttpEntity entity = response.getEntity(); if (entity == null || !entity.isStreaming()) { // connection not needed and (assumed to be) in re-usable state connHolder.releaseConnection(); return new HttpResponseProxy(response, null); } return new HttpResponseProxy(response, connHolder); //...... }
MainClientExec的execute方法在通過requestExecutor.execute(request, managedConn, context)獲取到response的時(shí)候,會(huì)根據(jù)reuseStrategy.keepAlive(response, context)來判斷該conn是reusable還是nonReusable的,最后在成功場景,entity為null或者不是streaming的會(huì)執(zhí)行connHolder.releaseConnection(),異常場景執(zhí)行connHolder.abortConnection()
DefaultClientConnectionReuseStrategy
org/apache/http/impl/client/DefaultClientConnectionReuseStrategy.java
public class DefaultClientConnectionReuseStrategy extends DefaultConnectionReuseStrategy { public static final DefaultClientConnectionReuseStrategy INSTANCE = new DefaultClientConnectionReuseStrategy(); @Override public boolean keepAlive(final HttpResponse response, final HttpContext context) { final HttpRequest request = (HttpRequest) context.getAttribute(HttpCoreContext.HTTP_REQUEST); if (request != null) { final Header[] connHeaders = request.getHeaders(HttpHeaders.CONNECTION); if (connHeaders.length != 0) { final TokenIterator ti = new BasicTokenIterator(new BasicHeaderIterator(connHeaders, null)); while (ti.hasNext()) { final String token = ti.nextToken(); if (HTTP.CONN_CLOSE.equalsIgnoreCase(token)) { return false; } } } } return super.keepAlive(response, context); } }
DefaultClientConnectionReuseStrategy繼承了DefaultConnectionReuseStrategy,其keepAlive先判斷response的header有無Connection: close,沒有則返回false,有則調(diào)用super.keepAlive進(jìn)行進(jìn)一步判斷(`對(duì)于http1.0的返回false)
小結(jié)
httpclient的ConnectionHolder實(shí)現(xiàn)了ConnectionReleaseTrigger接口,它提供了isReusable、markReusable、markNonReusable、setValidFor、releaseConnection、abortConnection、cancel、close等方法;releaseConnection在連接復(fù)用則執(zhí)行manager.releaseConnection(validDuration為response的Keep-Alive返回的timeout參數(shù),若沒有則為-1
),連接不復(fù)用先執(zhí)行managedConn.close()再執(zhí)行manager.releaseConnection(validDuration為0
);abortConnection先執(zhí)行this.managedConn.shutdown(),再執(zhí)行manager.releaseConnection(validDuration為0
);
MainClientExec的execute方法在通過requestExecutor.execute(request, managedConn, context)獲取到response的時(shí)候,會(huì)根據(jù)reuseStrategy.keepAlive(response, context)來判斷該conn是reusable還是nonReusable的,最后在成功場景,entity為null或者不是streaming的會(huì)執(zhí)行connHolder.releaseConnection(),異常場景執(zhí)行connHolder.abortConnection()
DefaultClientConnectionReuseStrategy繼承了DefaultConnectionReuseStrategy,其keepAlive先判斷response的header有無Connection: close,沒有則返回false,有則調(diào)用super.keepAlive進(jìn)行進(jìn)一步判斷(`對(duì)于http1.0的返回false)
close與shutdown的區(qū)別在于close是優(yōu)雅關(guān)閉,會(huì)試圖flush內(nèi)部的output buffer,shutdown是強(qiáng)制關(guān)閉,不會(huì)試圖去flush內(nèi)部的buffer
以上就是httpclient ConnectionHolder連接池連接保持源碼解析的詳細(xì)內(nèi)容,更多關(guān)于httpclient ConnectionHolder連接保持的資料請關(guān)注腳本之家其它相關(guān)文章!
- httpclient connect連接請求方法源碼解讀
- httpclient getPoolEntryBlocking連接池方法源碼解讀
- httpclient staleConnectionCheckEnabled獲取連接流程解析
- 解讀httpclient的validateAfterInactivity連接池狀態(tài)檢測
- httpclient的disableConnectionState方法工作流程
- 探索HttpClient中的close方法及其對(duì)連接的影響
- HttpClient的RedirectStrategy重定向處理核心機(jī)制
- HttpClient HttpRoutePlanner接口確定請求目標(biāo)路由
相關(guān)文章
MySQL數(shù)據(jù)文件直接通過拷貝備份與恢復(fù)的操作方法
這篇文章主要介紹了MySQL數(shù)據(jù)文件直接通過拷貝備份與恢復(fù)的操作方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-09-09springboot配置druid多數(shù)據(jù)源的示例代碼
這篇文章主要介紹了springboot配置druid多數(shù)據(jù)源的示例代碼,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-09-09Java 實(shí)戰(zhàn)項(xiàng)目錘煉之樸素風(fēng)格個(gè)人博客系統(tǒng)的實(shí)現(xiàn)流程
讀萬卷書不如行萬里路,只學(xué)書上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實(shí)戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用Java+vue+Springboot+ssm+mysql+maven+redis實(shí)現(xiàn)一個(gè)樸素風(fēng)格的個(gè)人博客系統(tǒng),大家可以在過程中查缺補(bǔ)漏,提升水平2021-11-11深入了解JVM字節(jié)碼增強(qiáng)技術(shù)
這篇文章主要介紹了深入了解JVM字節(jié)碼增強(qiáng)技術(shù),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11詳解Java使用JMH進(jìn)行基準(zhǔn)性能測試
本文主要介紹了Java使用JMH進(jìn)行基準(zhǔn)性能測試,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11springboot整合swagger3報(bào)Unable to infer base&nbs
這篇文章主要介紹了springboot整合swagger3報(bào)Unable to infer base url錯(cuò)誤問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-05-05spring 或者spring boot 調(diào)整bean加載順序的方式
這篇文章主要介紹了spring 或者spring boot 調(diào)整bean加載順序的方式,本文通過實(shí)例代碼講解三種調(diào)整類加載順序的方式,代碼簡單易懂,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-03-03導(dǎo)入maven項(xiàng)目各個(gè)注解均報(bào)錯(cuò)的解決方案
這篇文章主要介紹了導(dǎo)入maven項(xiàng)目各個(gè)注解均報(bào)錯(cuò)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12