1、HttpClient链接池,当每次拿到链接后会校验链接是否还建立,在validateAfterInactivity时间内不重复校验(默认两秒),比如,validateAfterInactivity设置的是5s,上次使用链接是在1s前,则不会校验直接使用。
源码如下:
while(true) {
//从链接池中拿到链接
E leasedEntry = AbstractConnPool.this.getPoolEntryBlocking(route, state, timeout, timeUnit, this);
//如果validateAfterInactivity小于0,或上次使用加上validateAfterInactivity大于当前时间或校验是否是有效链接
if (AbstractConnPool.this.validateAfterInactivity <= 0 || leasedEntry.getUpdated() + (long)AbstractConnPool.this.validateAfterInactivity > System.currentTimeMillis() || AbstractConnPool.this.validate(leasedEntry)) {
this.entryRef.set(leasedEntry);
this.done.set(true);
AbstractConnPool.this.onLease(leasedEntry);
if (callback != null) {
callback.completed(leasedEntry);
}
PoolEntry var10000 = leasedEntry;
return var10000;
}
//关闭连接
leasedEntry.close();
AbstractConnPool.this.release(leasedEntry, false);
}
2、校验链接是通过input读取判断是否大于0,当链接不可以用的时候读出来的是-1,通过setSoTimeout来避免阻塞,链接本来是空闲链接所以不会造成数据流失
AbstractConnPool.this.validate(leasedEntry)底层源码如下:
public boolean isStale() {
if (!this.isOpen()) {
return true;
} else {
try {
//如果读出来的结果小于0则代表无效链接
int bytesRead = this.fillInputBuffer(1);
return bytesRead < 0;
} catch (SocketTimeoutException var2) {
return false;
} catch (IOException var3) {
return true;
}
}
}
private int fillInputBuffer(int timeout) throws IOException {
Socket socket = (Socket)this.socketHolder.get();
int oldtimeout = socket.getSoTimeout();
int var4;
try {
//设置超时长度,避免阻塞
socket.setSoTimeout(timeout);
var4 = this.inBuffer.fillBuffer();
} finally {
socket.setSoTimeout(oldtimeout);
}
return var4;
}
3、如果使用无效的链接的话会抛出如下异常,Connection reset(发送时链接就不可用)
connect_reset.png
4、NoHttpResponseException出现原因:客户端发送时,链接是可用的,读取数据时链接服务器主动关闭连接会导致这个异常,服务器出现这种异常的原因可能为:
当服务器端由于负载过大等情况发生时,可能会导致在收到请求后无法处理(比如没有足够的线程资源),会直接丢弃链接而不进行处理。此时客户端就回报错:NoHttpResponseException。 建议出现这种情况时,可以选择重试
NoHttpResponse.png
网友评论