diff --git a/epmet-module/resi-group/resi-group-server/src/main/java/com/epmet/config/GracefulShutdownConfig.java b/epmet-module/resi-group/resi-group-server/src/main/java/com/epmet/config/GracefulShutdownConfig.java new file mode 100644 index 0000000000..c43854a583 --- /dev/null +++ b/epmet-module/resi-group/resi-group-server/src/main/java/com/epmet/config/GracefulShutdownConfig.java @@ -0,0 +1,24 @@ +package com.epmet.config; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.servlet.server.ServletWebServerFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * 优雅停机配置 + * matchIfMissing:当缺少shutdown.graceful.enable配置的时候,是否加载该配置类。true:缺少也加载,false:默认的,缺少配置不加载,即不生效 + */ +@Configuration +@ConditionalOnProperty(prefix = "shutdown.graceful", name = "enable", havingValue = "true", matchIfMissing = false) +public class GracefulShutdownConfig { + + @Bean + public ServletWebServerFactory servletContainer(GracefulShutdownTomcat gracefulShutdownTomcat) { + TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory(); + tomcat.addConnectorCustomizers(gracefulShutdownTomcat); + return tomcat; + } + +} diff --git a/epmet-module/resi-group/resi-group-server/src/main/java/com/epmet/config/GracefulShutdownTomcat.java b/epmet-module/resi-group/resi-group-server/src/main/java/com/epmet/config/GracefulShutdownTomcat.java new file mode 100644 index 0000000000..117a658b32 --- /dev/null +++ b/epmet-module/resi-group/resi-group-server/src/main/java/com/epmet/config/GracefulShutdownTomcat.java @@ -0,0 +1,52 @@ +package com.epmet.config; + +import com.epmet.commons.tools.exception.RenException; +import net.bytebuddy.implementation.bytecode.Throw; +import org.apache.catalina.connector.Connector; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer; +import org.springframework.context.ApplicationListener; +import org.springframework.context.event.ContextClosedEvent; +import org.springframework.stereotype.Component; + +import java.util.concurrent.Executor; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +@EnableConfigurationProperties(ShutdownProperties.class) +@Component +public class GracefulShutdownTomcat implements TomcatConnectorCustomizer, ApplicationListener { + + private static final Logger logger = LoggerFactory.getLogger(GracefulShutdownTomcat.class); + + @Autowired + private ShutdownProperties shutdownProperties; + + private volatile Connector connector; + + @Override + public void customize(Connector connector) { + this.connector = connector; + } + @Override + public void onApplicationEvent(ContextClosedEvent contextClosedEvent) { + this.connector.pause(); + Executor executor = this.connector.getProtocolHandler().getExecutor(); + long waitTimeSecs = shutdownProperties.getGraceful().getWaitTimeSecs(); + if (executor instanceof ThreadPoolExecutor) { + try { + ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executor; + threadPoolExecutor.shutdown(); + if (!threadPoolExecutor.awaitTermination(waitTimeSecs, TimeUnit.SECONDS)) { + String msg = String.format("Tomcat在【%s】秒内优雅停机失败,请手动处理", waitTimeSecs); + logger.error(msg); + } + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + } + } + } +} \ No newline at end of file diff --git a/epmet-module/resi-group/resi-group-server/src/main/java/com/epmet/config/ShutdownProperties.java b/epmet-module/resi-group/resi-group-server/src/main/java/com/epmet/config/ShutdownProperties.java new file mode 100644 index 0000000000..6be38ccc93 --- /dev/null +++ b/epmet-module/resi-group/resi-group-server/src/main/java/com/epmet/config/ShutdownProperties.java @@ -0,0 +1,17 @@ +package com.epmet.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; + +@ConfigurationProperties(prefix = "shutdown") +@Data +public class ShutdownProperties { + + private GracefulShutdownProperties graceful; + + @Data + public static class GracefulShutdownProperties { + private long waitTimeSecs = 30; + } + +} diff --git a/epmet-module/resi-group/resi-group-server/src/main/java/com/epmet/modules/test/TestController.java b/epmet-module/resi-group/resi-group-server/src/main/java/com/epmet/modules/test/TestController.java index e68a222f27..c86286bfc5 100644 --- a/epmet-module/resi-group/resi-group-server/src/main/java/com/epmet/modules/test/TestController.java +++ b/epmet-module/resi-group/resi-group-server/src/main/java/com/epmet/modules/test/TestController.java @@ -18,4 +18,13 @@ public class TestController { return new Result().ok(requestServerNameAndPort); } + @PostMapping("shutdown") + public Result testShutdown() throws InterruptedException { + for (int i = 1; i <= 10; i++) { + System.out.println(i); + Thread.sleep(1000l); + } + return new Result(); + } + } diff --git a/epmet-module/resi-group/resi-group-server/src/main/resources/bootstrap.yml b/epmet-module/resi-group/resi-group-server/src/main/resources/bootstrap.yml index 717cff838d..fad0c9c313 100644 --- a/epmet-module/resi-group/resi-group-server/src/main/resources/bootstrap.yml +++ b/epmet-module/resi-group/resi-group-server/src/main/resources/bootstrap.yml @@ -139,4 +139,10 @@ thread: dingTalk: robot: webHook: @dingTalk.robot.webHook@ - secret: @dingTalk.robot.secret@ \ No newline at end of file + secret: @dingTalk.robot.secret@ + +# 停机选项 +shutdown: + graceful: + enable: true #是否开启优雅停机 + waitTimeSecs: 3 # 优雅停机等待时间,超过30秒,发出告警 \ No newline at end of file