@@ -123,11 +123,32 @@ public static void scanUnusedClient() {
123123 });
124124 unusedClientMap .forEach ((bConfig , value ) -> value .forEach (e -> {
125125 try {
126+ RpcClientProxy proxy = (RpcClientProxy ) e ;
127+ // Double-check before closing: ensure the client is still idle to avoid closing a client in use.
128+ // This prevents race condition where getOrCreateClient() gets a client right before it's closed.
129+ if (!isIdleTimeout (bConfig , proxy )) {
130+ // lastUsedNanos was updated, meaning a business thread is using it, try to put it back
131+ Map <String , RpcClientProxy > clientMap = CLUSTER_MAP .get (bConfig );
132+ if (clientMap != null ) {
133+ RpcClientProxy existing = clientMap .putIfAbsent (
134+ proxy .getProtocolConfig ().toUniqId (), proxy );
135+ if (existing == null ) {
136+ // Successfully put back, do not close
137+ logger .info ("RpcClient {} rescued from closing due to recent usage" ,
138+ proxy .getProtocolConfig ().toSimpleString ());
139+ return ;
140+ }
141+ }
142+ // Failed to put back (a new client already exists), still need to close the old one
143+ }
126144 e .close ();
127- } finally {
128145 logger .warn ("RpcClient in clusterName={}, naming={}, remove rpc client{}, due to unused time > {} ms" ,
129146 bConfig .getName (), bConfig .getNamingOptions ().getServiceNaming (),
130147 e .getProtocolConfig ().toSimpleString (), bConfig .getIdleTimeout ());
148+ } catch (Exception ex ) {
149+ logger .error ("Failed to close RpcClient in clusterName={}, naming={}, client={}" ,
150+ bConfig .getName (), bConfig .getNamingOptions ().getServiceNaming (),
151+ e .getProtocolConfig ().toSimpleString (), ex );
131152 }
132153 }));
133154 }
@@ -322,4 +343,4 @@ public boolean equals(Object obj) {
322343 }
323344 }
324345
325- }
346+ }
0 commit comments