關(guān)于HttpClient 引發(fā)的線程太多導(dǎo)致FullGc的問題
CloseableHttpClient httpClient = HttpClients.custom() .setConnectionManager(connectionManager) .setMaxConnTotal(400) .setMaxConnPerRoute(150) .evictExpiredConnections() .build();
evictExpiredConnections 這個配置作用:
設(shè)置一個定時線程,定時清理閑置連接,可以將這個定時時間設(shè)置為 keep alive timeout 時間的一半以保證超時前回收
每個httpClient 對象都會有自己獨立的定時線程

這樣如果應(yīng)用中httpClient對象很多,就會導(dǎo)致上圖中線程太多
源碼中,如果設(shè)置了evictExpiredConnections 會有下面一段邏輯
List<Closeable> closeablesCopy = closeables != null ? new ArrayList<Closeable>(closeables) : null;
if (!this.connManagerShared) {
if (closeablesCopy == null) {
closeablesCopy = new ArrayList<Closeable>(1);
}
final HttpClientConnectionManager cm = connManagerCopy;
if (evictExpiredConnections || evictIdleConnections) {
final IdleConnectionEvictor connectionEvictor = new IdleConnectionEvictor(cm,
maxIdleTime > 0 ? maxIdleTime : 10, maxIdleTimeUnit != null ? maxIdleTimeUnit : TimeUnit.SECONDS,
maxIdleTime, maxIdleTimeUnit);
closeablesCopy.add(new Closeable() {
@Override
public void close() throws IOException {
connectionEvictor.shutdown();
try {
connectionEvictor.awaitTermination(1L, TimeUnit.SECONDS);
} catch (final InterruptedException interrupted) {
Thread.currentThread().interrupt();
}
}
});
connectionEvictor.start();
}
closeablesCopy.add(new Closeable() {
@Override
public void close() throws IOException {
cm.shutdown();
}
});
}
IdleConnectionEvictor 對象是
public final class IdleConnectionEvictor {
private final HttpClientConnectionManager connectionManager;
private final ThreadFactory threadFactory;
private final Thread thread;
private final long sleepTimeMs;
private final long maxIdleTimeMs;
private volatile Exception exception;
public IdleConnectionEvictor(
final HttpClientConnectionManager connectionManager,
final ThreadFactory threadFactory,
final long sleepTime, final TimeUnit sleepTimeUnit,
final long maxIdleTime, final TimeUnit maxIdleTimeUnit) {
this.connectionManager = Args.notNull(connectionManager, "Connection manager");
this.threadFactory = threadFactory != null ? threadFactory : new DefaultThreadFactory();
this.sleepTimeMs = sleepTimeUnit != null ? sleepTimeUnit.toMillis(sleepTime) : sleepTime;
this.maxIdleTimeMs = maxIdleTimeUnit != null ? maxIdleTimeUnit.toMillis(maxIdleTime) : maxIdleTime;
this.thread = this.threadFactory.newThread(new Runnable() {
@Override
public void run() {
try {
while (!Thread.currentThread().isInterrupted()) {
Thread.sleep(sleepTimeMs);
connectionManager.closeExpiredConnections();
if (maxIdleTimeMs > 0) {
connectionManager.closeIdleConnections(maxIdleTimeMs, TimeUnit.MILLISECONDS);
}
}
} catch (final Exception ex) {
exception = ex;
}
}
});
}
會出現(xiàn)一個線程,這個線程里面就是去關(guān)閉超時不用的閑置鏈接
到此這篇關(guān)于關(guān)于HttpClient 引發(fā)的線程太多導(dǎo)致FullGc的問題的文章就介紹到這了,更多相關(guān)HttpClient 引發(fā)的線程太多導(dǎo)致FullGc內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot利用Junit動態(tài)代理實現(xiàn)Mock方法
說到Spring Boot 單元測試主要有兩個主流集成分別是Mockito,Junit,這個各有特點,在實際開發(fā)中,我想要的測試框架應(yīng)該是這個框架集成者,本文給大家介紹了SpringBoot利用Junit動態(tài)代理實現(xiàn)Mock方法,需要的朋友可以參考下2024-04-04
在同一個類中調(diào)用帶有@Transactional注解的方法示例
這篇文章主要為大家介紹了在同一個類中調(diào)用帶有@Transactional注解的方法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-04-04
rabbitmq消息ACK確認(rèn)機制及發(fā)送失敗處理方式
這篇文章主要介紹了rabbitmq消息ACK確認(rèn)機制及發(fā)送失敗處理方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-12-12

