解讀httpclient的validateAfterInactivity連接池狀態(tài)檢測(cè)
序
本文主要研究一下httpclient的validateAfterInactivity
validateAfterInactivity
org/apache/http/pool/AbstractConnPool.java
@Contract(threading = ThreadingBehavior.SAFE_CONDITIONAL) public abstract class AbstractConnPool<T, C, E extends PoolEntry<T, C>> implements ConnPool<T, E>, ConnPoolControl<T> { private final Lock lock; private final Condition condition; private final ConnFactory<T, C> connFactory; private final Map<T, RouteSpecificPool<T, C, E>> routeToPool; private final Set<E> leased; private final LinkedList<E> available; private final LinkedList<Future<E>> pending; private final Map<T, Integer> maxPerRoute; private volatile boolean isShutDown; private volatile int defaultMaxPerRoute; private volatile int maxTotal; private volatile int validateAfterInactivity; public AbstractConnPool( final ConnFactory<T, C> connFactory, final int defaultMaxPerRoute, final int maxTotal) { super(); this.connFactory = Args.notNull(connFactory, "Connection factory"); this.defaultMaxPerRoute = Args.positive(defaultMaxPerRoute, "Max per route value"); this.maxTotal = Args.positive(maxTotal, "Max total value"); this.lock = new ReentrantLock(); this.condition = this.lock.newCondition(); this.routeToPool = new HashMap<T, RouteSpecificPool<T, C, E>>(); this.leased = new HashSet<E>(); this.available = new LinkedList<E>(); this.pending = new LinkedList<Future<E>>(); this.maxPerRoute = new HashMap<T, Integer>(); } //...... /** * @return the number of milliseconds * @since 4.4 */ public int getValidateAfterInactivity() { return this.validateAfterInactivity; } /** * @param ms the number of milliseconds * @since 4.4 */ public void setValidateAfterInactivity(final int ms) { this.validateAfterInactivity = ms; } }
AbstractConnPool定義了validateAfterInactivity屬性,與defaultMaxPerRoute、maxTotal不同,該屬性沒(méi)有在構(gòu)造器參數(shù)中,而是提供了setter來(lái)設(shè)置
PoolingHttpClientConnectionManager
org/apache/http/impl/conn/PoolingHttpClientConnectionManager.java
@Contract(threading = ThreadingBehavior.SAFE_CONDITIONAL) public class PoolingHttpClientConnectionManager implements HttpClientConnectionManager, ConnPoolControl<HttpRoute>, Closeable { public PoolingHttpClientConnectionManager( final HttpClientConnectionOperator httpClientConnectionOperator, final HttpConnectionFactory<HttpRoute, ManagedHttpClientConnection> connFactory, final long timeToLive, final TimeUnit timeUnit) { super(); this.configData = new ConfigData(); this.pool = new CPool(new InternalConnectionFactory( this.configData, connFactory), 2, 20, timeToLive, timeUnit); this.pool.setValidateAfterInactivity(2000); this.connectionOperator = Args.notNull(httpClientConnectionOperator, "HttpClientConnectionOperator"); this.isShutDown = new AtomicBoolean(false); } /** * Defines period of inactivity in milliseconds after which persistent connections must * be re-validated prior to being {@link #leaseConnection(java.util.concurrent.Future, * long, java.util.concurrent.TimeUnit) leased} to the consumer. Non-positive value passed * to this method disables connection validation. This check helps detect connections * that have become stale (half-closed) while kept inactive in the pool. * * @see #leaseConnection(java.util.concurrent.Future, long, java.util.concurrent.TimeUnit) * * @since 4.4 */ public void setValidateAfterInactivity(final int ms) { pool.setValidateAfterInactivity(ms); } //...... }
PoolingHttpClientConnectionManager默認(rèn)設(shè)置pool的validateAfterInactivity為2000ms,另外也提供了setValidateAfterInactivity方法
lease
org/apache/http/pool/AbstractConnPool.java
/** * {@inheritDoc} * <p> * Please note that this class does not maintain its own pool of execution * {@link Thread}s. Therefore, one <b>must</b> call {@link Future#get()} * or {@link Future#get(long, TimeUnit)} method on the {@link Future} * returned by this method in order for the lease operation to complete. */ @Override public Future<E> lease(final T route, final Object state, final FutureCallback<E> callback) { Args.notNull(route, "Route"); Asserts.check(!this.isShutDown, "Connection pool shut down"); return new Future<E>() { private final AtomicBoolean cancelled = new AtomicBoolean(false); private final AtomicBoolean done = new AtomicBoolean(false); private final AtomicReference<E> entryRef = new AtomicReference<E>(null); @Override public boolean cancel(final boolean mayInterruptIfRunning) { if (done.compareAndSet(false, true)) { cancelled.set(true); lock.lock(); try { condition.signalAll(); } finally { lock.unlock(); } if (callback != null) { callback.cancelled(); } return true; } return false; } @Override public boolean isCancelled() { return cancelled.get(); } @Override public boolean isDone() { return done.get(); } @Override public E get() throws InterruptedException, ExecutionException { try { return get(0L, TimeUnit.MILLISECONDS); } catch (final TimeoutException ex) { throw new ExecutionException(ex); } } @Override public E get(final long timeout, final TimeUnit timeUnit) throws InterruptedException, ExecutionException, TimeoutException { for (;;) { synchronized (this) { try { final E entry = entryRef.get(); if (entry != null) { return entry; } if (done.get()) { throw new ExecutionException(operationAborted()); } final E leasedEntry = getPoolEntryBlocking(route, state, timeout, timeUnit, this); if (validateAfterInactivity > 0) { if (leasedEntry.getUpdated() + validateAfterInactivity <= System.currentTimeMillis()) { if (!validate(leasedEntry)) { leasedEntry.close(); release(leasedEntry, false); continue; } } } if (done.compareAndSet(false, true)) { entryRef.set(leasedEntry); done.set(true); onLease(leasedEntry); if (callback != null) { callback.completed(leasedEntry); } return leasedEntry; } else { release(leasedEntry, true); throw new ExecutionException(operationAborted()); } } catch (final IOException ex) { if (done.compareAndSet(false, true)) { if (callback != null) { callback.failed(ex); } } throw new ExecutionException(ex); } } } } }; }
AbstractConnPool的lease方法返回一個(gè)future,其get方法通過(guò)getPoolEntryBlocking(route, state, timeout, timeUnit, this)獲取leasedEntry,之后判斷validateAfterInactivity是否大于0,大于0則判斷l(xiāng)easedEntry.getUpdated()+validateAfterInactivity是否小于等于當(dāng)前時(shí)間,是則執(zhí)行validate方法,validate不通過(guò)則close該entry然后release,然后繼續(xù)循環(huán)執(zhí)行g(shù)etPoolEntryBlocking
validate
org/apache/http/impl/conn/CPool.java
protected boolean validate(final CPoolEntry entry) { return !entry.getConnection().isStale(); }
CPool的validate則是通過(guò)entry.getConnection().isStale()來(lái)判斷
isStale
org/apache/http/impl/AbstractHttpClientConnection.java
public boolean isStale() { if (!isOpen()) { return true; } if (isEof()) { return true; } try { this.inBuffer.isDataAvailable(1); return isEof(); } catch (final SocketTimeoutException ex) { return false; } catch (final IOException ex) { return true; } }
AbstractHttpClientConnection的isStale先判斷是否open,再判斷是否eof,最后執(zhí)行inBuffer.isDataAvailable(1),出現(xiàn)SocketTimeoutException返回false,出現(xiàn)IOException返回true,若沒(méi)有異常返回isEof
小結(jié)
apache的httpclient的AbstractConnPool提供了validateAfterInactivity屬性,默認(rèn)是2000ms,它的作用是在連接池獲取連接的時(shí)候進(jìn)行判斷,如果該entry的最后更新時(shí)間+validateAfterInactivity小于等于當(dāng)前時(shí)間,則執(zhí)行validate方法,validate不通過(guò)則繼續(xù)循環(huán)獲取連接。而validate方法則是通過(guò)connection的isStale來(lái)判斷的。該屬性有助于檢測(cè)連接池中空閑連接的stale(half-closed)狀態(tài),避免真正使用的時(shí)候報(bào)錯(cuò)。
以上就是httpclient的validateAfterInactivity連接池狀態(tài)檢測(cè)的詳細(xì)內(nèi)容,更多關(guān)于httpclient validateAfterInactivity的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- httpclient connect連接請(qǐng)求方法源碼解讀
- httpclient getPoolEntryBlocking連接池方法源碼解讀
- httpclient staleConnectionCheckEnabled獲取連接流程解析
- httpclient的disableConnectionState方法工作流程
- 探索HttpClient中的close方法及其對(duì)連接的影響
- HttpClient的RedirectStrategy重定向處理核心機(jī)制
- HttpClient HttpRoutePlanner接口確定請(qǐng)求目標(biāo)路由
- httpclient ConnectionHolder連接池連接保持源碼解析
相關(guān)文章
redis redisson 集合的使用案例(RList、Rset、RMap)
這篇文章主要介紹了redis redisson 集合的使用案例(RList、Rset、RMap),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07深入理解@component與@Configuration注解
這篇文章主要介紹了深入理解@component與@Configuration注解,從Spring3.0,@Configuration用于定義配置類,可替換xml配置文件,被注解的類內(nèi)部包含有一個(gè)或多個(gè)被@Bean注解的方法,這些方法將會(huì)被掃描,并用于構(gòu)建bean定義,初始化Spring容器,需要的朋友可以參考下2023-11-11java servlet手機(jī)app訪問(wèn)接口(三)高德地圖云存儲(chǔ)及檢索
這篇文章主要為大家詳細(xì)介紹了java servlet手機(jī)app訪問(wèn)接口(三),高德地圖云存儲(chǔ)及檢索,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-12-12Java壓縮和解壓縮ZIP文件實(shí)戰(zhàn)案例
這篇文章主要給大家介紹了關(guān)于Java壓縮和解壓縮ZIP文件的相關(guān)資料,ZIP是一種較為常見(jiàn)的壓縮形式,最近項(xiàng)目中遇到了再Java中壓縮和解壓縮zip文件的需求,特此分享給大家,需要的朋友可以參考下2023-07-07Java基礎(chǔ)教程之理解Annotation詳細(xì)介紹
這篇文章主要介紹了Java基礎(chǔ)教程之理解Annotation詳細(xì)介紹的相關(guān)資料,需要的朋友可以參考下2017-01-01