diff --git a/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/config/DynamicThreadPoolAutoConfiguration.java b/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/config/DynamicThreadPoolAutoConfiguration.java index 1b0cb995..27b05996 100644 --- a/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/config/DynamicThreadPoolAutoConfiguration.java +++ b/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/config/DynamicThreadPoolAutoConfiguration.java @@ -43,6 +43,7 @@ import cn.hippo4j.springboot.starter.controller.ThreadPoolAdapterController; import cn.hippo4j.springboot.starter.controller.WebThreadPoolController; import cn.hippo4j.springboot.starter.controller.WebThreadPoolRunStateController; import cn.hippo4j.springboot.starter.core.BaseThreadDetailStateHandler; +import cn.hippo4j.springboot.starter.core.ClientShutdown; import cn.hippo4j.springboot.starter.core.ClientWorker; import cn.hippo4j.springboot.starter.core.DynamicThreadPoolSubscribeConfig; import cn.hippo4j.springboot.starter.core.ServerThreadPoolDynamicRefresh; @@ -62,6 +63,7 @@ import cn.hippo4j.springboot.starter.support.DynamicThreadPoolConfigService; import cn.hippo4j.springboot.starter.support.DynamicThreadPoolPostProcessor; import cn.hippo4j.springboot.starter.support.ThreadPoolPluginRegisterPostProcessor; import lombok.AllArgsConstructor; +import org.checkerframework.checker.units.qual.C; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.ImportAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; @@ -247,4 +249,8 @@ public class DynamicThreadPoolAutoConfiguration { return new ThreadPoolPluginRegisterPostProcessor(); } + @Bean + public ClientShutdown clientShutdown() { + return new ClientShutdown(); + } } diff --git a/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/core/ClientShutdown.java b/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/core/ClientShutdown.java new file mode 100644 index 00000000..ef1546f7 --- /dev/null +++ b/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/core/ClientShutdown.java @@ -0,0 +1,26 @@ +package cn.hippo4j.springboot.starter.core; + + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import lombok.Getter; + +public class ClientShutdown { + + @Getter + private volatile boolean prepareClose = false; + + private CountDownLatch countDownLatch = new CountDownLatch(1); + + private final static Long TIME_OUT_SECOND = 5L; + + public void prepareDestroy() throws InterruptedException { + prepareClose = true; + countDownLatch.await(TIME_OUT_SECOND, TimeUnit.SECONDS); + } + + public void countDown() { + countDownLatch.countDown(); + } + +} diff --git a/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/core/DiscoveryClient.java b/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/core/DiscoveryClient.java index 92cb52e3..c5908101 100644 --- a/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/core/DiscoveryClient.java +++ b/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/core/DiscoveryClient.java @@ -54,6 +54,7 @@ public class DiscoveryClient implements DisposableBean { private final String appPathIdentifier; + public DiscoveryClient(HttpAgent httpAgent, InstanceInfo instanceInfo) { this.httpAgent = httpAgent; this.instanceInfo = instanceInfo; @@ -92,8 +93,7 @@ public class DiscoveryClient implements DisposableBean { String clientCloseUrlPath = Constants.BASE_PATH + "/client/close"; Result clientCloseResult; try { - // close scheduledExecutor - this.scheduler.shutdown(); + this.prepareDestroy(); String groupKeyIp = new StringBuilder() .append(instanceInfo.getGroupKey()) .append(Constants.GROUP_KEY_DELIMITER) @@ -115,6 +115,13 @@ public class DiscoveryClient implements DisposableBean { } } + private void prepareDestroy() throws InterruptedException { + // close scheduled + this.scheduler.shutdown(); + // try to make sure the ClientWorker is closed first + ApplicationContextHolder.getBean(ClientShutdown.class).prepareDestroy(); + } + public class HeartbeatThread implements Runnable { @Override diff --git a/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/remote/ServerHttpAgent.java b/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/remote/ServerHttpAgent.java index 67f688f4..96c95a6a 100644 --- a/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/remote/ServerHttpAgent.java +++ b/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/remote/ServerHttpAgent.java @@ -24,6 +24,7 @@ import cn.hippo4j.common.toolkit.http.HttpUtil; import cn.hippo4j.common.web.base.Result; import cn.hippo4j.common.design.builder.ThreadFactoryBuilder; import cn.hippo4j.springboot.starter.config.BootstrapProperties; +import cn.hippo4j.springboot.starter.core.ClientShutdown; import cn.hippo4j.springboot.starter.security.SecurityProxy; import java.util.HashMap; @@ -45,6 +46,8 @@ public class ServerHttpAgent implements HttpAgent { private ServerHealthCheck serverHealthCheck; + private ClientShutdown clientShutdown; + private ScheduledExecutorService executorService; private final long securityInfoRefreshIntervalMills = TimeUnit.SECONDS.toMillis(5); @@ -110,6 +113,9 @@ public class ServerHttpAgent implements HttpAgent { public Result httpPostByConfig(String path, Map headers, Map paramValues, long readTimeoutMs) { isHealthStatus(); injectSecurityInfo(paramValues); + if (isPrepareClose()) { + return null; + } return HttpUtil.post(buildUrl(path), headers, paramValues, readTimeoutMs, Result.class); } @@ -129,6 +135,18 @@ public class ServerHttpAgent implements HttpAgent { serverHealthCheck.isHealthStatus(); } + + private boolean isPrepareClose() { + if (clientShutdown == null) { + clientShutdown = ApplicationContextHolder.getBean(ClientShutdown.class); + } + if (clientShutdown.isPrepareClose()) { + clientShutdown.countDown(); + return true; + } + return false; + } + private Map injectSecurityInfo(Map params) { if (StringUtil.isNotBlank(securityProxy.getAccessToken())) { params.put(Constants.ACCESS_TOKEN, securityProxy.getAccessToken());