7878import java .util .concurrent .ConcurrentMap ;
7979import java .util .concurrent .ExecutionException ;
8080import java .util .concurrent .Future ;
81+ import java .util .concurrent .ScheduledExecutorService ;
82+ import java .util .concurrent .ScheduledThreadPoolExecutor ;
83+ import java .util .concurrent .TimeUnit ;
8184import java .util .concurrent .atomic .AtomicInteger ;
8285import java .util .stream .Collectors ;
8386
@@ -127,6 +130,8 @@ public class Rest5Client implements Closeable {
127130 private final WarningsHandler warningsHandler ;
128131 private final boolean compressionEnabled ;
129132 private final boolean metaHeaderEnabled ;
133+ private final ScheduledExecutorService healthCheckExecutor ;
134+ private volatile boolean closed = false ;
130135
131136 Rest5Client (
132137 CloseableHttpAsyncClient client ,
@@ -148,6 +153,19 @@ public class Rest5Client implements Closeable {
148153 this .compressionEnabled = compressionEnabled ;
149154 this .metaHeaderEnabled = metaHeaderEnabled ;
150155 setNodes (nodes );
156+
157+ // 初始化连接池健康检查执行器
158+ this .healthCheckExecutor = new ScheduledThreadPoolExecutor (1 , r -> {
159+ Thread thread = new Thread (r , "elasticsearch-rest-client-health-check" );
160+ thread .setDaemon (true );
161+ return thread ;
162+ });
163+
164+ // 启动定期健康检查(每30秒执行一次)
165+ this .healthCheckExecutor .scheduleAtFixedRate (
166+ this ::performHealthCheck ,
167+ 30 , 30 , TimeUnit .SECONDS
168+ );
151169 }
152170
153171 /**
@@ -584,9 +602,66 @@ private void onFailure(Node node) {
584602 failureListener .onFailure (node );
585603 }
586604
605+ @ Override
606+ /**
607+ * 执行连接池健康检查
608+ */
609+ private void performHealthCheck () {
610+ if (closed ) {
611+ return ;
612+ }
613+
614+ try {
615+ // 检查客户端状态
616+ if (client instanceof org .apache .hc .client5 .http .impl .async .CloseableHttpAsyncClientImpl ) {
617+ org .apache .hc .client5 .http .impl .async .CloseableHttpAsyncClientImpl clientImpl =
618+ (org .apache .hc .client5 .http .impl .async .CloseableHttpAsyncClientImpl ) client ;
619+
620+ // 获取连接管理器
621+ org .apache .hc .client5 .http .impl .nio .PoolingAsyncClientConnectionManager connectionManager =
622+ (org .apache .hc .client5 .http .impl .nio .PoolingAsyncClientConnectionManager ) clientImpl .getConnectionManager ();
623+
624+ // 检查连接池状态
625+ int totalConnections = connectionManager .getTotalStats ().getAvailable () +
626+ connectionManager .getTotalStats ().getLeased () +
627+ connectionManager .getTotalStats ().getPending () +
628+ connectionManager .getTotalStats ().getMax ();
629+
630+ // 如果连接数超过阈值,输出警告日志
631+ if (totalConnections > connectionManager .getMaxTotal ()) {
632+ logger .warn ("Connection pool usage exceeded maximum limit. Total connections: " + totalConnections + ", Max: " + connectionManager .getMaxTotal ());
633+ }
634+
635+ // 定期清理过期连接
636+ connectionManager .closeExpiredConnections ();
637+ connectionManager .closeIdleConnections (Timeout .of (5 , TimeUnit .MINUTES ));
638+ }
639+ } catch (Exception e ) {
640+ logger .debug ("Failed to perform connection pool health check" , e );
641+ }
642+ }
643+
587644 @ Override
588645 public void close () throws IOException {
589- client .close ();
646+ closed = true ;
647+
648+ // 关闭健康检查执行器
649+ if (healthCheckExecutor != null ) {
650+ healthCheckExecutor .shutdown ();
651+ try {
652+ if (!healthCheckExecutor .awaitTermination (5 , TimeUnit .SECONDS )) {
653+ healthCheckExecutor .shutdownNow ();
654+ }
655+ } catch (InterruptedException e ) {
656+ Thread .currentThread ().interrupt ();
657+ healthCheckExecutor .shutdownNow ();
658+ }
659+ }
660+
661+ // 关闭HTTP客户端
662+ if (client != null ) {
663+ client .close ();
664+ }
590665 }
591666
592667 /**
0 commit comments