解讀httpclient的validateAfterInactivity連接池狀態(tài)檢測
序
本文主要研究一下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不同,該屬性沒有在構(gòu)造器參數(shù)中,而是提供了setter來設(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方法通過getPoolEntryBlocking(route, state, timeout, timeUnit, this)獲取leasedEntry,之后判斷validateAfterInactivity是否大于0,大于0則判斷l(xiāng)easedEntry.getUpdated()+validateAfterInactivity是否小于等于當(dāng)前時(shí)間,是則執(zhí)行validate方法,validate不通過則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則是通過entry.getConnection().isStale()來判斷
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,若沒有異常返回isEof
小結(jié)
apache的httpclient的AbstractConnPool提供了validateAfterInactivity屬性,默認(rèn)是2000ms,它的作用是在連接池獲取連接的時(shí)候進(jìn)行判斷,如果該entry的最后更新時(shí)間+validateAfterInactivity小于等于當(dāng)前時(shí)間,則執(zhí)行validate方法,validate不通過則繼續(xù)循環(huán)獲取連接。而validate方法則是通過connection的isStale來判斷的。該屬性有助于檢測連接池中空閑連接的stale(half-closed)狀態(tài),避免真正使用的時(shí)候報(bào)錯(cuò)。
以上就是httpclient的validateAfterInactivity連接池狀態(tài)檢測的詳細(xì)內(nèi)容,更多關(guān)于httpclient validateAfterInactivity的資料請關(guān)注腳本之家其它相關(guān)文章!
- httpclient connect連接請求方法源碼解讀
- httpclient getPoolEntryBlocking連接池方法源碼解讀
- httpclient staleConnectionCheckEnabled獲取連接流程解析
- httpclient的disableConnectionState方法工作流程
- 探索HttpClient中的close方法及其對連接的影響
- HttpClient的RedirectStrategy重定向處理核心機(jī)制
- HttpClient HttpRoutePlanner接口確定請求目標(biāo)路由
- httpclient ConnectionHolder連接池連接保持源碼解析
相關(guān)文章
Java實(shí)現(xiàn)bmp和jpeg圖片格式互轉(zhuǎn)
本文主要介紹了Java實(shí)現(xiàn)bmp和jpeg圖片格式互轉(zhuǎn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04
淺析Java如何高效將PDF轉(zhuǎn)換為高質(zhì)量TIFF圖片
在文檔處理和歸檔系統(tǒng)中,將PDF文件轉(zhuǎn)換為TIFF格式是一項(xiàng)非常常見的需求,本文將介紹如何使用Java通過Spire.PDF?for?Java庫,快速實(shí)現(xiàn)PDF到TIFF的轉(zhuǎn)換,希望對大家有所幫助2026-04-04
Java?關(guān)鍵字break和continue的使用說明
這篇文章主要介紹了Java?關(guān)鍵字break和continue的使用,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-03-03
Java Optional解決空指針異??偨Y(jié)(java 8 功能)
這篇文章主要介紹了Java Optional解決空指針異常總結(jié)(java 8 功能),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11

