httpclient getPoolEntryBlocking連接池方法源碼解讀
序
本文主要研究一下httpclient的getPoolEntryBlocking
getPoolEntryBlocking
org/apache/http/pool/AbstractConnPool.java
private E getPoolEntryBlocking( final T route, final Object state, final long timeout, final TimeUnit timeUnit, final Future<E> future) throws IOException, InterruptedException, ExecutionException, TimeoutException { Date deadline = null; if (timeout > 0) { deadline = new Date (System.currentTimeMillis() + timeUnit.toMillis(timeout)); } this.lock.lock(); try { final RouteSpecificPool<T, C, E> pool = getPool(route); E entry; for (;;) { Asserts.check(!this.isShutDown, "Connection pool shut down"); if (future.isCancelled()) { throw new ExecutionException(operationAborted()); } for (;;) { entry = pool.getFree(state); if (entry == null) { break; } if (entry.isExpired(System.currentTimeMillis())) { entry.close(); } if (entry.isClosed()) { this.available.remove(entry); pool.free(entry, false); } else { break; } } if (entry != null) { this.available.remove(entry); this.leased.add(entry); onReuse(entry); return entry; } // New connection is needed final int maxPerRoute = getMax(route); // Shrink the pool prior to allocating a new connection final int excess = Math.max(0, pool.getAllocatedCount() + 1 - maxPerRoute); if (excess > 0) { for (int i = 0; i < excess; i++) { final E lastUsed = pool.getLastUsed(); if (lastUsed == null) { break; } lastUsed.close(); this.available.remove(lastUsed); pool.remove(lastUsed); } } if (pool.getAllocatedCount() < maxPerRoute) { final int totalUsed = this.leased.size(); final int freeCapacity = Math.max(this.maxTotal - totalUsed, 0); if (freeCapacity > 0) { final int totalAvailable = this.available.size(); if (totalAvailable > freeCapacity - 1) { if (!this.available.isEmpty()) { final E lastUsed = this.available.removeLast(); lastUsed.close(); final RouteSpecificPool<T, C, E> otherpool = getPool(lastUsed.getRoute()); otherpool.remove(lastUsed); } } final C conn = this.connFactory.create(route); entry = pool.add(conn); this.leased.add(entry); return entry; } } boolean success = false; try { pool.queue(future); this.pending.add(future); if (deadline != null) { success = this.condition.awaitUntil(deadline); } else { this.condition.await(); success = true; } if (future.isCancelled()) { throw new ExecutionException(operationAborted()); } } finally { // In case of 'success', we were woken up by the // connection pool and should now have a connection // waiting for us, or else we're shutting down. // Just continue in the loop, both cases are checked. pool.unqueue(future); this.pending.remove(future); } // check for spurious wakeup vs. timeout if (!success && (deadline != null && deadline.getTime() <= System.currentTimeMillis())) { break; } } throw new TimeoutException("Timeout waiting for connection"); } finally { this.lock.unlock(); } }
AbstractConnPool提供了getPoolEntryBlocking,lease內(nèi)部就是通過這個方法來獲取連接的。它主要是通過pool.getFree獲取空閑連接,然后進(jìn)行過期判斷,再判斷是否close,如果已經(jīng)close則從available中移除,獲取成功的話則從available移除,添加到leased然后返回。如果獲取不到則先判斷連接是否超出maxPerRoute,超出則先移除最近使用的,之后在沒有超出maxPerRoute的條件下通過connFactory.create創(chuàng)建然后返回,超出則放入到pending中進(jìn)行等待
InternalConnectionFactory
org/apache/http/impl/conn/PoolingHttpClientConnectionManager.java
static class InternalConnectionFactory implements ConnFactory<HttpRoute, ManagedHttpClientConnection> { private final ConfigData configData; private final HttpConnectionFactory<HttpRoute, ManagedHttpClientConnection> connFactory; InternalConnectionFactory( final ConfigData configData, final HttpConnectionFactory<HttpRoute, ManagedHttpClientConnection> connFactory) { super(); this.configData = configData != null ? configData : new ConfigData(); this.connFactory = connFactory != null ? connFactory : ManagedHttpClientConnectionFactory.INSTANCE; } @Override public ManagedHttpClientConnection create(final HttpRoute route) throws IOException { ConnectionConfig config = null; if (route.getProxyHost() != null) { config = this.configData.getConnectionConfig(route.getProxyHost()); } if (config == null) { config = this.configData.getConnectionConfig(route.getTargetHost()); } if (config == null) { config = this.configData.getDefaultConnectionConfig(); } if (config == null) { config = ConnectionConfig.DEFAULT; } return this.connFactory.create(route, config); } }
InternalConnectionFactory實現(xiàn)了ConnFactory接口,其create方法委托給ManagedHttpClientConnectionFactory.INSTANCE
ManagedHttpClientConnectionFactory
public class ManagedHttpClientConnectionFactory implements HttpConnectionFactory<HttpRoute, ManagedHttpClientConnection> { private static final AtomicLong COUNTER = new AtomicLong(); public static final ManagedHttpClientConnectionFactory INSTANCE = new ManagedHttpClientConnectionFactory(); private final Log log = LogFactory.getLog(DefaultManagedHttpClientConnection.class); private final Log headerLog = LogFactory.getLog("org.apache.http.headers"); private final Log wireLog = LogFactory.getLog("org.apache.http.wire"); private final HttpMessageWriterFactory<HttpRequest> requestWriterFactory; private final HttpMessageParserFactory<HttpResponse> responseParserFactory; private final ContentLengthStrategy incomingContentStrategy; private final ContentLengthStrategy outgoingContentStrategy; //...... public ManagedHttpClientConnection create(final HttpRoute route, final ConnectionConfig config) { final ConnectionConfig cconfig = config != null ? config : ConnectionConfig.DEFAULT; CharsetDecoder charDecoder = null; CharsetEncoder charEncoder = null; final Charset charset = cconfig.getCharset(); final CodingErrorAction malformedInputAction = cconfig.getMalformedInputAction() != null ? cconfig.getMalformedInputAction() : CodingErrorAction.REPORT; final CodingErrorAction unmappableInputAction = cconfig.getUnmappableInputAction() != null ? cconfig.getUnmappableInputAction() : CodingErrorAction.REPORT; if (charset != null) { charDecoder = charset.newDecoder(); charDecoder.onMalformedInput(malformedInputAction); charDecoder.onUnmappableCharacter(unmappableInputAction); charEncoder = charset.newEncoder(); charEncoder.onMalformedInput(malformedInputAction); charEncoder.onUnmappableCharacter(unmappableInputAction); } final String id = "http-outgoing-" + Long.toString(COUNTER.getAndIncrement()); return new LoggingManagedHttpClientConnection( id, log, headerLog, wireLog, cconfig.getBufferSize(), cconfig.getFragmentSizeHint(), charDecoder, charEncoder, cconfig.getMessageConstraints(), incomingContentStrategy, outgoingContentStrategy, requestWriterFactory, responseParserFactory); } }
ManagedHttpClientConnectionFactory的create方法創(chuàng)建的是LoggingManagedHttpClientConnection,它繼承了DefaultManagedHttpClientConnection增加了logging的特性,而DefaultManagedHttpClientConnection繼承了DefaultBHttpClientConnection,聲明實現(xiàn)了ManagedHttpClientConnection
小結(jié)
AbstractConnPool提供了getPoolEntryBlocking,lease內(nèi)部就是通過這個方法來獲取連接的。它主要是通過pool.getFree獲取空閑連接,然后進(jìn)行過期判斷,再判斷是否close,如果已經(jīng)close則從available中移除,獲取成功的話則從available移除,添加到leased然后返回。如果獲取不到則先判斷連接是否超出maxPerRoute,超出則先移除最近使用的,之后在沒有超出maxPerRoute的條件下通過connFactory.create創(chuàng)建然后返回,超出則放入到pending中進(jìn)行等待。
MainClientExec優(yōu)先通過connManager.requestConnection是經(jīng)過連接池管理的,如果連接不夠用,通過connFactory.create創(chuàng)建新的ManagedHttpClientConnection,最后MainClientExec會再判斷一下managedConn是否open,沒有的話會通過establishRoute來建立連接(HttpClientConnectionManager.connect會創(chuàng)建socket然后進(jìn)行connect然后bind到managedConn)
以上就是httpclient getPoolEntryBlocking連接池方法源碼解讀的詳細(xì)內(nèi)容,更多關(guān)于httpclient getPoolEntryBlocking的資料請關(guān)注腳本之家其它相關(guān)文章!
- httpclient connect連接請求方法源碼解讀
- httpclient staleConnectionCheckEnabled獲取連接流程解析
- 解讀httpclient的validateAfterInactivity連接池狀態(tài)檢測
- httpclient的disableConnectionState方法工作流程
- 探索HttpClient中的close方法及其對連接的影響
- HttpClient的RedirectStrategy重定向處理核心機(jī)制
- HttpClient HttpRoutePlanner接口確定請求目標(biāo)路由
- httpclient ConnectionHolder連接池連接保持源碼解析
相關(guān)文章
SpringBoot中MockMVC單元測試的實現(xiàn)
Mock是一種用于模擬和替換類的對象的方法,以便在單元測試中獨立于外部資源進(jìn)行測試,本文主要介紹了SpringBoot中MockMVC單元測試的實現(xiàn),具有應(yīng)該的參考價值,感興趣的可以了解一下2024-02-02Spring Boot 中的 @ConditionalOnBean 注解作用及基
在 Spring Boot 中,@ConditionalOnBean 可以幫助我們根據(jù) 是否存在特定 Bean 來 動態(tài)注冊 Bean,廣泛用于 按需加載、自動配置 等場景,本文給大家介紹Spring Boot 中的 @ConditionalOnBean 注解,感興趣的朋友一起看看吧2025-04-04Spring Boot 2.x中Actuator的一些知識點
這篇文章主要給大家介紹了關(guān)于Spring Boot 2.x中Actuator的一些知識點,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Spring Boot 2.x具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09