From 21b5cc25d0bea08aeafff10061fb7bd517f358a8 Mon Sep 17 00:00:00 2001 From: eric-zc1 Date: Thu, 18 Dec 2025 10:54:53 +0800 Subject: [PATCH] Double-check before closing --- .../core/cluster/RpcClusterClientManager.java | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/trpc-core/src/main/java/com/tencent/trpc/core/cluster/RpcClusterClientManager.java b/trpc-core/src/main/java/com/tencent/trpc/core/cluster/RpcClusterClientManager.java index 8fbdbf2f4..3e3ad865a 100644 --- a/trpc-core/src/main/java/com/tencent/trpc/core/cluster/RpcClusterClientManager.java +++ b/trpc-core/src/main/java/com/tencent/trpc/core/cluster/RpcClusterClientManager.java @@ -123,11 +123,32 @@ public static void scanUnusedClient() { }); unusedClientMap.forEach((bConfig, value) -> value.forEach(e -> { try { + RpcClientProxy proxy = (RpcClientProxy) e; + // Double-check before closing: ensure the client is still idle to avoid closing a client in use. + // This prevents race condition where getOrCreateClient() gets a client right before it's closed. + if (!isIdleTimeout(bConfig, proxy)) { + // lastUsedNanos was updated, meaning a business thread is using it, try to put it back + Map clientMap = CLUSTER_MAP.get(bConfig); + if (clientMap != null) { + RpcClientProxy existing = clientMap.putIfAbsent( + proxy.getProtocolConfig().toUniqId(), proxy); + if (existing == null) { + // Successfully put back, do not close + logger.info("RpcClient {} rescued from closing due to recent usage", + proxy.getProtocolConfig().toSimpleString()); + return; + } + } + // Failed to put back (a new client already exists), still need to close the old one + } e.close(); - } finally { logger.warn("RpcClient in clusterName={}, naming={}, remove rpc client{}, due to unused time > {} ms", bConfig.getName(), bConfig.getNamingOptions().getServiceNaming(), e.getProtocolConfig().toSimpleString(), bConfig.getIdleTimeout()); + } catch (Exception ex) { + logger.error("Failed to close RpcClient in clusterName={}, naming={}, client={}", + bConfig.getName(), bConfig.getNamingOptions().getServiceNaming(), + e.getProtocolConfig().toSimpleString(), ex); } })); } @@ -322,4 +343,4 @@ public boolean equals(Object obj) { } } -} \ No newline at end of file +}