From 9f94d9d29a77b5891820b6344d457cbe06c47036 Mon Sep 17 00:00:00 2001 From: yanrongzhen Date: Thu, 16 Mar 2023 20:04:13 +0800 Subject: [PATCH] Bruceyan/issue#1106 (#1125) * Refactor the web adapter module to be compatible with Spring Boot 1.x versions. * fix: Prevent NPE exceptions from being thrown when certain parameters are not configured. * fix: Add some ERROR logs. * fix: Add some notes. --- .../web/AbstractWebThreadPoolService.java | 52 ++++++++--- .../DefaultAbstractWebThreadPoolService.java | 72 +++++++++++++++ .../web/IWebThreadPoolHandlerSupport.java | 65 ++++++++++++++ .../adapter/web/WebIpAndPortHolder.java | 4 +- .../web/WebThreadPoolHandlerChoose.java | 1 + .../adapter/web/WebThreadPoolService.java | 16 ++-- .../DefaultJettyWebThreadPoolHandler.java | 60 +++++++++++++ .../jetty/JettyWebThreadPoolHandlerAdapt.java | 26 ++++++ .../JettyWebThreadPoolHandlerSupport.java} | 21 +++-- .../DefaultTomcatWebThreadPoolHandler.java | 72 +++++++++++++++ .../TomcatWebThreadPoolHandlerAdapt.java | 26 ++++++ .../TomcatWebThreadPoolHandlerSupport.java} | 45 ++++------ .../DefaultUndertowWebThreadPoolHandler.java | 69 ++++++++++++++ .../UndertowWebThreadPoolHandlerAdapt.java | 26 ++++++ .../UndertowWebThreadPoolHandlerSupport.java} | 42 ++++----- .../pom.xml | 15 ++++ .../WebThreadPoolHandlerConfiguration1x.java | 89 +++++++++++++++++++ .../web/AbstractWebThreadPoolService1x.java | 49 ++++++++++ .../jetty/JettyWebThreadPoolHandler1x.java | 54 +++++++++++ .../tomcat/TomcatWebThreadPoolHandler1x.java | 56 ++++++++++++ .../UndertowWebThreadPoolHandler1x.java | 63 +++++++++++++ .../main/resources/META-INF/spring.factories | 4 +- .../event/WebExecutorRefreshListener.java | 12 +++ .../WebThreadPoolHandlerConfiguration.java | 25 ++++-- 24 files changed, 869 insertions(+), 95 deletions(-) create mode 100644 hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/DefaultAbstractWebThreadPoolService.java create mode 100644 hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/IWebThreadPoolHandlerSupport.java create mode 100644 hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/jetty/DefaultJettyWebThreadPoolHandler.java create mode 100644 hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/jetty/JettyWebThreadPoolHandlerAdapt.java rename hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/{JettyWebThreadPoolHandler.java => jetty/JettyWebThreadPoolHandlerSupport.java} (87%) create mode 100644 hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/tomcat/DefaultTomcatWebThreadPoolHandler.java create mode 100644 hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/tomcat/TomcatWebThreadPoolHandlerAdapt.java rename hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/{TomcatWebThreadPoolHandler.java => tomcat/TomcatWebThreadPoolHandlerSupport.java} (85%) create mode 100644 hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/undertow/DefaultUndertowWebThreadPoolHandler.java create mode 100644 hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/undertow/UndertowWebThreadPoolHandlerAdapt.java rename hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/{UndertowWebThreadPoolHandler.java => undertow/UndertowWebThreadPoolHandlerSupport.java} (86%) create mode 100644 hippo4j-spring-boot/hippo4j-config-spring-boot-1x-starter/src/main/java/cn/hippo4j/config/springboot1x/starter/config/WebThreadPoolHandlerConfiguration1x.java create mode 100644 hippo4j-spring-boot/hippo4j-config-spring-boot-1x-starter/src/main/java/cn/hippo4j/config/springboot1x/starter/web/AbstractWebThreadPoolService1x.java create mode 100644 hippo4j-spring-boot/hippo4j-config-spring-boot-1x-starter/src/main/java/cn/hippo4j/config/springboot1x/starter/web/jetty/JettyWebThreadPoolHandler1x.java create mode 100644 hippo4j-spring-boot/hippo4j-config-spring-boot-1x-starter/src/main/java/cn/hippo4j/config/springboot1x/starter/web/tomcat/TomcatWebThreadPoolHandler1x.java create mode 100644 hippo4j-spring-boot/hippo4j-config-spring-boot-1x-starter/src/main/java/cn/hippo4j/config/springboot1x/starter/web/undertow/UndertowWebThreadPoolHandler1x.java diff --git a/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/AbstractWebThreadPoolService.java b/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/AbstractWebThreadPoolService.java index bafdf678..910ff0f3 100644 --- a/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/AbstractWebThreadPoolService.java +++ b/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/AbstractWebThreadPoolService.java @@ -17,14 +17,14 @@ package cn.hippo4j.adapter.web; -import cn.hippo4j.common.config.ApplicationContextHolder; +import cn.hippo4j.common.enums.WebContainerEnum; +import cn.hippo4j.common.model.ThreadPoolBaseInfo; +import cn.hippo4j.common.model.ThreadPoolParameter; +import cn.hippo4j.common.model.ThreadPoolParameterInfo; +import cn.hippo4j.common.model.ThreadPoolRunStateInfo; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; -import org.springframework.boot.web.context.WebServerApplicationContext; -import org.springframework.boot.web.server.WebServer; -import org.springframework.context.ApplicationContext; - import java.util.concurrent.Executor; /** @@ -33,6 +33,12 @@ import java.util.concurrent.Executor; @Slf4j public abstract class AbstractWebThreadPoolService implements WebThreadPoolService, ApplicationRunner { + private final IWebThreadPoolHandlerSupport support; + + public AbstractWebThreadPoolService(IWebThreadPoolHandlerSupport support) { + this.support = support; + } + /** * Thread pool executor */ @@ -41,17 +47,16 @@ public abstract class AbstractWebThreadPoolService implements WebThreadPoolServi /** * Get web thread pool by server * - * @param webServer * @return */ - protected abstract Executor getWebThreadPoolByServer(WebServer webServer); + protected abstract Executor getWebThreadPoolInternal(); @Override public Executor getWebThreadPool() { if (executor == null) { synchronized (AbstractWebThreadPoolService.class) { if (executor == null) { - executor = getWebThreadPoolByServer(getWebServer()); + executor = getWebThreadPoolInternal(); } } } @@ -59,16 +64,37 @@ public abstract class AbstractWebThreadPoolService implements WebThreadPoolServi } @Override - public WebServer getWebServer() { - ApplicationContext applicationContext = ApplicationContextHolder.getInstance(); - WebServer webServer = ((WebServerApplicationContext) applicationContext).getWebServer(); - return webServer; + public ThreadPoolBaseInfo simpleInfo() { + return support.simpleInfo(); + } + + @Override + public ThreadPoolParameter getWebThreadPoolParameter() { + return support.getWebThreadPoolParameter(); + } + + @Override + public ThreadPoolRunStateInfo getWebRunStateInfo() { + return support.getWebRunStateInfo(); } + @Override + public void updateWebThreadPool(ThreadPoolParameterInfo threadPoolParameterInfo) { + support.updateWebThreadPool(threadPoolParameterInfo); + } + + @Override + public WebContainerEnum getWebContainerType() { + return support.getWebContainerType(); + } + + /** + * Call-back after the web container has been started. + */ @Override public void run(ApplicationArguments args) { try { - getWebThreadPool(); + this.support.setExecutor(getWebThreadPool()); } catch (Exception ignored) { } } diff --git a/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/DefaultAbstractWebThreadPoolService.java b/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/DefaultAbstractWebThreadPoolService.java new file mode 100644 index 00000000..ebb98f0e --- /dev/null +++ b/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/DefaultAbstractWebThreadPoolService.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.hippo4j.adapter.web; + +import cn.hippo4j.common.config.ApplicationContextHolder; +import org.springframework.boot.web.context.WebServerApplicationContext; +import org.springframework.boot.web.server.WebServer; +import org.springframework.context.ApplicationContext; + +import java.util.concurrent.Executor; + +/** + * Default WebThreadPoolService abstract class, + * reuses common capabilities for web container operations. + */ +public abstract class DefaultAbstractWebThreadPoolService extends AbstractWebThreadPoolService { + + public DefaultAbstractWebThreadPoolService(IWebThreadPoolHandlerSupport support) { + super(support); + } + + /** + * Get the internal abstract method of the web container thread pool, + * to be implemented by subclasses. + * @return + */ + @Override + protected Executor getWebThreadPoolInternal() { + return getWebThreadPoolByServer(getWebServer()); + } + + /** + * Get port by server. + * @return web port + */ + @Override + public Integer getPort() { + return getWebServer().getPort(); + } + + /** + * Get the thread pool object of the current web container based on the WebServer. + * @param webServer current Web-Server. + * @return Thread pool executor of the current web container. + */ + protected abstract Executor getWebThreadPoolByServer(WebServer webServer); + + /** + * Get current Web Server. + * @return webServer current Web-Server. + */ + public WebServer getWebServer() { + ApplicationContext applicationContext = ApplicationContextHolder.getInstance(); + return ((WebServerApplicationContext) applicationContext).getWebServer(); + } + +} diff --git a/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/IWebThreadPoolHandlerSupport.java b/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/IWebThreadPoolHandlerSupport.java new file mode 100644 index 00000000..0b25afdd --- /dev/null +++ b/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/IWebThreadPoolHandlerSupport.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.hippo4j.adapter.web; + +import cn.hippo4j.common.enums.WebContainerEnum; +import cn.hippo4j.common.model.ThreadPoolBaseInfo; +import cn.hippo4j.common.model.ThreadPoolParameter; +import cn.hippo4j.common.model.ThreadPoolParameterInfo; +import cn.hippo4j.common.model.ThreadPoolRunStateInfo; + +import java.util.concurrent.Executor; + +/** + * Support class for WebThreadPoolHandler, providing some common methods. + */ +public interface IWebThreadPoolHandlerSupport { + + /** + * Set the Executor to the current class + * so that other methods in the class can function properly. + * @param executor + */ + void setExecutor(Executor executor); + + /** + * Retrieve the simple information of the thread pool. + * @return + */ + ThreadPoolBaseInfo simpleInfo(); + + /** + * Retrieve the parameter of the thread pool. + * @return + */ + ThreadPoolParameter getWebThreadPoolParameter(); + + /** + * Retrieve the run state of the thread pool. + * @return + */ + ThreadPoolRunStateInfo getWebRunStateInfo(); + + /** + * Update thread pool parameters. + * @param threadPoolParameterInfo New parameters + */ + void updateWebThreadPool(ThreadPoolParameterInfo threadPoolParameterInfo); + + WebContainerEnum getWebContainerType(); +} diff --git a/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/WebIpAndPortHolder.java b/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/WebIpAndPortHolder.java index 687e3eee..dbe23f28 100644 --- a/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/WebIpAndPortHolder.java +++ b/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/WebIpAndPortHolder.java @@ -23,7 +23,6 @@ import cn.hippo4j.common.toolkit.Assert; import cn.hippo4j.common.toolkit.StringUtil; import cn.hippo4j.core.toolkit.inet.InetUtils; import lombok.NoArgsConstructor; -import org.springframework.boot.web.server.WebServer; import org.springframework.core.env.ConfigurableEnvironment; import java.util.Arrays; @@ -86,8 +85,7 @@ public class WebIpAndPortHolder { WebThreadPoolHandlerChoose webThreadPoolHandlerChoose = ApplicationContextHolder.getBean(WebThreadPoolHandlerChoose.class); WebThreadPoolService webThreadPoolService = webThreadPoolHandlerChoose.choose(); // When get the port at startup, can get the message: "port xxx was already in use" or use two ports - WebServer webServer = webThreadPoolService.getWebServer(); - port = webServer.getPort(); + port = webThreadPoolService.getPort(); } return new WebIpAndPortInfo(ip, String.valueOf(port)); diff --git a/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/WebThreadPoolHandlerChoose.java b/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/WebThreadPoolHandlerChoose.java index 1d94d379..3b08bdb2 100644 --- a/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/WebThreadPoolHandlerChoose.java +++ b/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/WebThreadPoolHandlerChoose.java @@ -17,6 +17,7 @@ package cn.hippo4j.adapter.web; +import cn.hippo4j.adapter.web.WebThreadPoolService; import cn.hippo4j.common.config.ApplicationContextHolder; import cn.hippo4j.common.web.exception.ServiceException; import lombok.extern.slf4j.Slf4j; diff --git a/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/WebThreadPoolService.java b/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/WebThreadPoolService.java index aae89244..082c890f 100644 --- a/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/WebThreadPoolService.java +++ b/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/WebThreadPoolService.java @@ -22,7 +22,6 @@ import cn.hippo4j.common.model.ThreadPoolBaseInfo; import cn.hippo4j.common.model.ThreadPoolParameter; import cn.hippo4j.common.model.ThreadPoolParameterInfo; import cn.hippo4j.common.model.ThreadPoolRunStateInfo; -import org.springframework.boot.web.server.WebServer; import java.util.concurrent.Executor; @@ -38,6 +37,12 @@ public interface WebThreadPoolService { */ Executor getWebThreadPool(); + /** + * Get web container port. + * @return + */ + Integer getPort(); + /** * Simple info. * @@ -66,15 +71,6 @@ public interface WebThreadPoolService { */ void updateWebThreadPool(ThreadPoolParameterInfo threadPoolParameterInfo); - /** - * Get web server. - * - * @return - */ - default WebServer getWebServer() { - return null; - } - /** * resolve current web container type. * diff --git a/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/jetty/DefaultJettyWebThreadPoolHandler.java b/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/jetty/DefaultJettyWebThreadPoolHandler.java new file mode 100644 index 00000000..407221c9 --- /dev/null +++ b/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/jetty/DefaultJettyWebThreadPoolHandler.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.hippo4j.adapter.web.jetty; + +import cn.hippo4j.adapter.web.DefaultAbstractWebThreadPoolService; +import cn.hippo4j.adapter.web.IWebThreadPoolHandlerSupport; +import cn.hippo4j.common.constant.ChangeThreadPoolConstants; +import cn.hippo4j.common.enums.WebContainerEnum; +import cn.hippo4j.common.model.ThreadPoolBaseInfo; +import cn.hippo4j.common.model.ThreadPoolParameter; +import cn.hippo4j.common.model.ThreadPoolParameterInfo; +import cn.hippo4j.common.model.ThreadPoolRunStateInfo; +import cn.hippo4j.common.toolkit.ReflectUtil; +import lombok.extern.slf4j.Slf4j; +import org.eclipse.jetty.util.thread.QueuedThreadPool; +import org.springframework.boot.web.embedded.jetty.JettyWebServer; +import org.springframework.boot.web.server.WebServer; + +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.Executor; + +/** + * Jetty web thread pool handler. + */ +@Slf4j +public class DefaultJettyWebThreadPoolHandler extends DefaultAbstractWebThreadPoolService + implements + JettyWebThreadPoolHandlerAdapt { + + public DefaultJettyWebThreadPoolHandler() { + super(new JettyWebThreadPoolHandlerSupport()); + } + + /** + * Get the thread pool object of the current web container based on the WebServer. + * @param webServer current Web-Server. + * @return Thread pool executor of the current web container. + */ + @Override + protected Executor getWebThreadPoolByServer(WebServer webServer) { + JettyWebServer jettyWebServer = (JettyWebServer) webServer; + return jettyWebServer.getServer().getThreadPool(); + } + +} diff --git a/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/jetty/JettyWebThreadPoolHandlerAdapt.java b/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/jetty/JettyWebThreadPoolHandlerAdapt.java new file mode 100644 index 00000000..49613c5f --- /dev/null +++ b/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/jetty/JettyWebThreadPoolHandlerAdapt.java @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.hippo4j.adapter.web.jetty; + +import cn.hippo4j.adapter.web.WebThreadPoolService; + +/** + * Adapt interface of Jetty web thread-pool handler. + */ +public interface JettyWebThreadPoolHandlerAdapt extends WebThreadPoolService { +} diff --git a/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/JettyWebThreadPoolHandler.java b/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/jetty/JettyWebThreadPoolHandlerSupport.java similarity index 87% rename from hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/JettyWebThreadPoolHandler.java rename to hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/jetty/JettyWebThreadPoolHandlerSupport.java index c4a04da5..1bae64f4 100644 --- a/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/JettyWebThreadPoolHandler.java +++ b/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/jetty/JettyWebThreadPoolHandlerSupport.java @@ -15,8 +15,9 @@ * limitations under the License. */ -package cn.hippo4j.adapter.web; +package cn.hippo4j.adapter.web.jetty; +import cn.hippo4j.adapter.web.IWebThreadPoolHandlerSupport; import cn.hippo4j.common.constant.ChangeThreadPoolConstants; import cn.hippo4j.common.enums.WebContainerEnum; import cn.hippo4j.common.model.ThreadPoolBaseInfo; @@ -26,22 +27,26 @@ import cn.hippo4j.common.model.ThreadPoolRunStateInfo; import cn.hippo4j.common.toolkit.ReflectUtil; import lombok.extern.slf4j.Slf4j; import org.eclipse.jetty.util.thread.QueuedThreadPool; -import org.springframework.boot.web.embedded.jetty.JettyWebServer; -import org.springframework.boot.web.server.WebServer; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Executor; /** - * Jetty web thread pool handler. + * The supporting class for WebThreadPoolHandler, + * which facilitates the creation of a Jetty web container. */ @Slf4j -public class JettyWebThreadPoolHandler extends AbstractWebThreadPoolService { +public class JettyWebThreadPoolHandlerSupport implements IWebThreadPoolHandlerSupport { + private Executor executor; + + /** + * A callback will be invoked and the Executor will be set up when the web container has been started. + * @param executor Thread-pool executor in Jetty container. + */ @Override - protected Executor getWebThreadPoolByServer(WebServer webServer) { - JettyWebServer jettyWebServer = (JettyWebServer) webServer; - return jettyWebServer.getServer().getThreadPool(); + public void setExecutor(Executor executor) { + this.executor = executor; } @Override diff --git a/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/tomcat/DefaultTomcatWebThreadPoolHandler.java b/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/tomcat/DefaultTomcatWebThreadPoolHandler.java new file mode 100644 index 00000000..601385da --- /dev/null +++ b/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/tomcat/DefaultTomcatWebThreadPoolHandler.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.hippo4j.adapter.web.tomcat; + +import cn.hippo4j.adapter.web.DefaultAbstractWebThreadPoolService; +import cn.hippo4j.adapter.web.IWebThreadPoolHandlerSupport; +import cn.hippo4j.common.enums.WebContainerEnum; +import cn.hippo4j.common.model.ThreadPoolBaseInfo; +import cn.hippo4j.common.model.ThreadPoolParameter; +import cn.hippo4j.common.model.ThreadPoolParameterInfo; +import cn.hippo4j.common.model.ThreadPoolRunStateInfo; +import cn.hippo4j.core.executor.state.AbstractThreadPoolRuntime; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.web.embedded.tomcat.TomcatWebServer; +import org.springframework.boot.web.server.WebServer; + +import java.util.concurrent.Executor; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * Tomcat web thread pool handler. + */ +@Slf4j +public class DefaultTomcatWebThreadPoolHandler extends DefaultAbstractWebThreadPoolService + implements + TomcatWebThreadPoolHandlerAdapt { + + private final AtomicBoolean cacheFlag = new AtomicBoolean(Boolean.FALSE); + + private static String exceptionMessage; + + public DefaultTomcatWebThreadPoolHandler(AbstractThreadPoolRuntime runtime) { + super(new TomcatWebThreadPoolHandlerSupport(runtime)); + } + + /** + * Get the thread pool object of the current web container based on the WebServer. + * @param webServer current Web-Server. + * @return Thread pool executor of the current web container. + */ + @Override + protected Executor getWebThreadPoolByServer(WebServer webServer) { + if (cacheFlag.get()) { + log.warn("Exception getting Tomcat thread pool. Exception message: {}", exceptionMessage); + return null; + } + Executor tomcatExecutor = null; + try { + tomcatExecutor = ((TomcatWebServer) webServer).getTomcat().getConnector().getProtocolHandler().getExecutor(); + } catch (Exception ex) { + cacheFlag.set(Boolean.TRUE); + exceptionMessage = ex.getMessage(); + log.error("Failed to get Tomcat thread pool. Message: {}", exceptionMessage); + } + return tomcatExecutor; + } +} diff --git a/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/tomcat/TomcatWebThreadPoolHandlerAdapt.java b/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/tomcat/TomcatWebThreadPoolHandlerAdapt.java new file mode 100644 index 00000000..d8229ab2 --- /dev/null +++ b/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/tomcat/TomcatWebThreadPoolHandlerAdapt.java @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.hippo4j.adapter.web.tomcat; + +import cn.hippo4j.adapter.web.WebThreadPoolService; + +/** + * Adapt interface of Tomcat web thread-pool handler. + */ +public interface TomcatWebThreadPoolHandlerAdapt extends WebThreadPoolService { +} diff --git a/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/TomcatWebThreadPoolHandler.java b/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/tomcat/TomcatWebThreadPoolHandlerSupport.java similarity index 85% rename from hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/TomcatWebThreadPoolHandler.java rename to hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/tomcat/TomcatWebThreadPoolHandlerSupport.java index f6869458..5c8b359c 100644 --- a/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/TomcatWebThreadPoolHandler.java +++ b/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/tomcat/TomcatWebThreadPoolHandlerSupport.java @@ -15,8 +15,9 @@ * limitations under the License. */ -package cn.hippo4j.adapter.web; +package cn.hippo4j.adapter.web.tomcat; +import cn.hippo4j.adapter.web.IWebThreadPoolHandlerSupport; import cn.hippo4j.common.constant.ChangeThreadPoolConstants; import cn.hippo4j.common.enums.WebContainerEnum; import cn.hippo4j.common.model.ThreadPoolBaseInfo; @@ -25,10 +26,7 @@ import cn.hippo4j.common.model.ThreadPoolParameterInfo; import cn.hippo4j.common.model.ThreadPoolRunStateInfo; import cn.hippo4j.common.toolkit.CalculateUtil; import cn.hippo4j.core.executor.state.AbstractThreadPoolRuntime; -import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.boot.web.embedded.tomcat.TomcatWebServer; -import org.springframework.boot.web.server.WebServer; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; @@ -36,36 +34,29 @@ import java.util.concurrent.BlockingQueue; import java.util.concurrent.Executor; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; /** - * Tomcat web thread pool handler. + * The supporting class for WebThreadPoolHandler, + * which facilitates the creation of a Tomcat web container. */ @Slf4j -@RequiredArgsConstructor -public class TomcatWebThreadPoolHandler extends AbstractWebThreadPoolService { +public class TomcatWebThreadPoolHandlerSupport implements IWebThreadPoolHandlerSupport { - private final AtomicBoolean cacheFlag = new AtomicBoolean(Boolean.FALSE); + private final AbstractThreadPoolRuntime runtime; - private static String exceptionMessage; + private Executor executor; - private final AbstractThreadPoolRuntime webThreadPoolRunStateHandler; + public TomcatWebThreadPoolHandlerSupport(AbstractThreadPoolRuntime runtime) { + this.runtime = runtime; + } + /** + * A callback will be invoked and the Executor will be set up when the web container has been started. + * @param executor Thread-pool executor in Tomcat container. + */ @Override - protected Executor getWebThreadPoolByServer(WebServer webServer) { - if (cacheFlag.get()) { - log.warn("Exception getting Tomcat thread pool. Exception message: {}", exceptionMessage); - return null; - } - Executor tomcatExecutor = null; - try { - tomcatExecutor = ((TomcatWebServer) webServer).getTomcat().getConnector().getProtocolHandler().getExecutor(); - } catch (Exception ex) { - cacheFlag.set(Boolean.TRUE); - exceptionMessage = ex.getMessage(); - log.error("Failed to get Tomcat thread pool. Message: {}", exceptionMessage); - } - return tomcatExecutor; + public void setExecutor(Executor executor) { + this.executor = executor; } @Override @@ -110,7 +101,7 @@ public class TomcatWebThreadPoolHandler extends AbstractWebThreadPoolService { @Override public ThreadPoolRunStateInfo getWebRunStateInfo() { if (executor instanceof ThreadPoolExecutor) { - return webThreadPoolRunStateHandler.getPoolRunState(null, executor); + return runtime.getPoolRunState(null, executor); } ThreadPoolRunStateInfo runStateInfo = new ThreadPoolRunStateInfo(); org.apache.tomcat.util.threads.ThreadPoolExecutor tomcatThreadPoolExecutor = (org.apache.tomcat.util.threads.ThreadPoolExecutor) executor; @@ -144,7 +135,7 @@ public class TomcatWebThreadPoolHandler extends AbstractWebThreadPoolService { String rejectedExecutionHandlerName = executor instanceof ThreadPoolExecutor ? ((ThreadPoolExecutor) executor).getRejectedExecutionHandler().getClass().getSimpleName() : tomcatThreadPoolExecutor.getRejectedExecutionHandler().getClass().getSimpleName(); runStateInfo.setRejectedName(rejectedExecutionHandlerName); - return webThreadPoolRunStateHandler.supplement(runStateInfo); + return runtime.supplement(runStateInfo); } @Override diff --git a/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/undertow/DefaultUndertowWebThreadPoolHandler.java b/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/undertow/DefaultUndertowWebThreadPoolHandler.java new file mode 100644 index 00000000..5d874549 --- /dev/null +++ b/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/undertow/DefaultUndertowWebThreadPoolHandler.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.hippo4j.adapter.web.undertow; + +import java.lang.reflect.Field; +import java.util.Objects; +import java.util.concurrent.Executor; + +import cn.hippo4j.adapter.web.DefaultAbstractWebThreadPoolService; +import cn.hippo4j.adapter.web.IWebThreadPoolHandlerSupport; +import cn.hippo4j.common.enums.WebContainerEnum; +import cn.hippo4j.common.model.ThreadPoolBaseInfo; +import cn.hippo4j.common.model.ThreadPoolParameter; +import cn.hippo4j.common.model.ThreadPoolParameterInfo; +import cn.hippo4j.common.model.ThreadPoolRunStateInfo; +import io.undertow.Undertow; +import lombok.extern.slf4j.Slf4j; + +import org.springframework.boot.web.embedded.undertow.UndertowServletWebServer; +import org.springframework.boot.web.server.WebServer; +import org.springframework.util.ReflectionUtils; + +/** + * Undertow web thread pool handler. + */ +@Slf4j +public class DefaultUndertowWebThreadPoolHandler extends DefaultAbstractWebThreadPoolService + implements + UndertowWebThreadPoolHandlerAdapt { + + private static final String UNDERTOW_NAME = "undertow"; + + public DefaultUndertowWebThreadPoolHandler() { + super(new UndertowWebThreadPoolHandlerSupport()); + } + + /** + * Get the thread pool object of the current web container based on the WebServer. + * @param webServer current Web-Server. + * @return Thread pool executor of the current web container. + */ + @Override + protected Executor getWebThreadPoolByServer(WebServer webServer) { + // There is no need to consider reflection performance because the fetch is a singleton. + // Springboot 2-3 version, can directly through reflection to obtain the undertow property + UndertowServletWebServer undertowServletWebServer = (UndertowServletWebServer) webServer; + Field undertowField = ReflectionUtils.findField(UndertowServletWebServer.class, UNDERTOW_NAME); + ReflectionUtils.makeAccessible(undertowField); + + Undertow undertow = (Undertow) ReflectionUtils.getField(undertowField, undertowServletWebServer); + return Objects.isNull(undertow) ? null : undertow.getWorker(); + } + +} diff --git a/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/undertow/UndertowWebThreadPoolHandlerAdapt.java b/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/undertow/UndertowWebThreadPoolHandlerAdapt.java new file mode 100644 index 00000000..208d8ebb --- /dev/null +++ b/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/undertow/UndertowWebThreadPoolHandlerAdapt.java @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.hippo4j.adapter.web.undertow; + +import cn.hippo4j.adapter.web.WebThreadPoolService; + +/** + * Adapt interface of Undertow web thread-pool handler. + */ +public interface UndertowWebThreadPoolHandlerAdapt extends WebThreadPoolService { +} diff --git a/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/UndertowWebThreadPoolHandler.java b/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/undertow/UndertowWebThreadPoolHandlerSupport.java similarity index 86% rename from hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/UndertowWebThreadPoolHandler.java rename to hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/undertow/UndertowWebThreadPoolHandlerSupport.java index 2408cd57..e37abe0f 100644 --- a/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/UndertowWebThreadPoolHandler.java +++ b/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/undertow/UndertowWebThreadPoolHandlerSupport.java @@ -15,15 +15,9 @@ * limitations under the License. */ -package cn.hippo4j.adapter.web; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; -import java.util.Objects; -import java.util.concurrent.Executor; +package cn.hippo4j.adapter.web.undertow; +import cn.hippo4j.adapter.web.IWebThreadPoolHandlerSupport; import cn.hippo4j.common.constant.ChangeThreadPoolConstants; import cn.hippo4j.common.enums.WebContainerEnum; import cn.hippo4j.common.model.ThreadPoolBaseInfo; @@ -32,33 +26,33 @@ import cn.hippo4j.common.model.ThreadPoolParameterInfo; import cn.hippo4j.common.model.ThreadPoolRunStateInfo; import cn.hippo4j.common.toolkit.CalculateUtil; import cn.hippo4j.core.executor.DynamicThreadPoolExecutor; -import io.undertow.Undertow; import lombok.extern.slf4j.Slf4j; +import org.springframework.util.ReflectionUtils; import org.xnio.Options; import org.xnio.XnioWorker; -import org.springframework.boot.web.embedded.undertow.UndertowServletWebServer; -import org.springframework.boot.web.server.WebServer; -import org.springframework.util.ReflectionUtils; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.concurrent.Executor; /** - * Undertow web thread pool handler. + * The supporting class for WebThreadPoolHandler, + * which facilitates the creation of a Undertow web container. */ @Slf4j -public class UndertowWebThreadPoolHandler extends AbstractWebThreadPoolService { +public class UndertowWebThreadPoolHandlerSupport implements IWebThreadPoolHandlerSupport { - private static final String UNDERTOW_NAME = "undertow"; + private Executor executor; + /** + * A callback will be invoked and the Executor will be set up when the web container has been started. + * @param executor Thread-pool executor in Undertow container. + */ @Override - protected Executor getWebThreadPoolByServer(WebServer webServer) { - // There is no need to consider reflection performance because the fetch is a singleton. - // Springboot 2-3 version, can directly through reflection to obtain the undertow property - UndertowServletWebServer undertowServletWebServer = (UndertowServletWebServer) webServer; - Field undertowField = ReflectionUtils.findField(UndertowServletWebServer.class, UNDERTOW_NAME); - ReflectionUtils.makeAccessible(undertowField); - - Undertow undertow = (Undertow) ReflectionUtils.getField(undertowField, undertowServletWebServer); - return Objects.isNull(undertow) ? null : undertow.getWorker(); + public void setExecutor(Executor executor) { + this.executor = executor; } @Override diff --git a/hippo4j-spring-boot/hippo4j-config-spring-boot-1x-starter/pom.xml b/hippo4j-spring-boot/hippo4j-config-spring-boot-1x-starter/pom.xml index 1e3e7d8d..b06d722e 100644 --- a/hippo4j-spring-boot/hippo4j-config-spring-boot-1x-starter/pom.xml +++ b/hippo4j-spring-boot/hippo4j-config-spring-boot-1x-starter/pom.xml @@ -22,5 +22,20 @@ hippo4j-config-spring-boot-starter ${project.version} + + org.springframework.boot + spring-boot-starter-tomcat + true + + + org.springframework.boot + spring-boot-starter-undertow + true + + + org.springframework.boot + spring-boot-starter-jetty + true + \ No newline at end of file diff --git a/hippo4j-spring-boot/hippo4j-config-spring-boot-1x-starter/src/main/java/cn/hippo4j/config/springboot1x/starter/config/WebThreadPoolHandlerConfiguration1x.java b/hippo4j-spring-boot/hippo4j-config-spring-boot-1x-starter/src/main/java/cn/hippo4j/config/springboot1x/starter/config/WebThreadPoolHandlerConfiguration1x.java new file mode 100644 index 00000000..7ba71536 --- /dev/null +++ b/hippo4j-spring-boot/hippo4j-config-spring-boot-1x-starter/src/main/java/cn/hippo4j/config/springboot1x/starter/config/WebThreadPoolHandlerConfiguration1x.java @@ -0,0 +1,89 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.hippo4j.config.springboot1x.starter.config; + +import cn.hippo4j.adapter.web.*; +import cn.hippo4j.adapter.web.WebThreadPoolRunStateHandler; +import cn.hippo4j.config.springboot1x.starter.web.jetty.JettyWebThreadPoolHandler1x; +import cn.hippo4j.config.springboot1x.starter.web.tomcat.TomcatWebThreadPoolHandler1x; +import cn.hippo4j.config.springboot1x.starter.web.undertow.UndertowWebThreadPoolHandler1x; +import cn.hippo4j.springboot.starter.adapter.web.WebThreadPoolHandlerConfiguration; +import io.undertow.Undertow; +import org.apache.catalina.Loader; +import org.apache.catalina.Server; +import org.apache.catalina.startup.Tomcat; +import org.eclipse.jetty.webapp.WebAppContext; +import org.springframework.boot.autoconfigure.AutoConfigureBefore; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.SearchStrategy; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.xnio.SslClientAuthMode; + +import javax.servlet.Servlet; + +/** + * Spring auto-configuration class for WebThreadPoolHandlers. + */ +@Configuration +@AutoConfigureBefore(WebThreadPoolHandlerConfiguration.class) +public class WebThreadPoolHandlerConfiguration1x { + + @Configuration + @ConditionalOnClass({Servlet.class, Tomcat.class}) + @ConditionalOnMissingBean(value = WebThreadPoolService.class, search = SearchStrategy.CURRENT) + static class EmbeddedTomcat { + + /** + * Nested configuration if Tomcat is being used. + */ + @Bean + public WebThreadPoolService tomcatWebThreadPoolHandler(WebThreadPoolRunStateHandler webThreadPoolRunStateHandler) { + return new TomcatWebThreadPoolHandler1x(webThreadPoolRunStateHandler); + } + } + + /** + * Nested configuration if Jetty is being used. + */ + @Configuration + @ConditionalOnClass({Servlet.class, Server.class, Loader.class, WebAppContext.class}) + @ConditionalOnMissingBean(value = WebThreadPoolService.class, search = SearchStrategy.CURRENT) + static class EmbeddedJetty { + + @Bean + public WebThreadPoolService jettyWebThreadPoolHandler() { + return new JettyWebThreadPoolHandler1x(); + } + } + + /** + * Nested configuration if Undertow is being used. + */ + @Configuration + @ConditionalOnClass({Servlet.class, Undertow.class, SslClientAuthMode.class}) + @ConditionalOnMissingBean(value = WebThreadPoolService.class, search = SearchStrategy.CURRENT) + static class EmbeddedUndertow { + + @Bean + public WebThreadPoolService undertowWebThreadPoolHandler() { + return new UndertowWebThreadPoolHandler1x(); + } + } +} diff --git a/hippo4j-spring-boot/hippo4j-config-spring-boot-1x-starter/src/main/java/cn/hippo4j/config/springboot1x/starter/web/AbstractWebThreadPoolService1x.java b/hippo4j-spring-boot/hippo4j-config-spring-boot-1x-starter/src/main/java/cn/hippo4j/config/springboot1x/starter/web/AbstractWebThreadPoolService1x.java new file mode 100644 index 00000000..333a4d07 --- /dev/null +++ b/hippo4j-spring-boot/hippo4j-config-spring-boot-1x-starter/src/main/java/cn/hippo4j/config/springboot1x/starter/web/AbstractWebThreadPoolService1x.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.hippo4j.config.springboot1x.starter.web; + +import cn.hippo4j.adapter.web.AbstractWebThreadPoolService; +import cn.hippo4j.adapter.web.IWebThreadPoolHandlerSupport; +import cn.hippo4j.common.config.ApplicationContextHolder; +import org.springframework.boot.context.embedded.EmbeddedServletContainer; +import org.springframework.boot.context.embedded.EmbeddedWebApplicationContext; + +/** + * Abstract class for adapting WebThreadPoolService to Spring 1.x version. + */ +public abstract class AbstractWebThreadPoolService1x extends AbstractWebThreadPoolService { + + public AbstractWebThreadPoolService1x(IWebThreadPoolHandlerSupport support) { + super(support); + } + + /** + * Get the embedded Servlet container from the Spring application context. + */ + protected EmbeddedServletContainer getContainer() { + return ((EmbeddedWebApplicationContext) ApplicationContextHolder.getInstance()).getEmbeddedServletContainer(); + } + + /** + * Get the port from web container. + */ + @Override + public Integer getPort() { + return getContainer().getPort(); + } +} diff --git a/hippo4j-spring-boot/hippo4j-config-spring-boot-1x-starter/src/main/java/cn/hippo4j/config/springboot1x/starter/web/jetty/JettyWebThreadPoolHandler1x.java b/hippo4j-spring-boot/hippo4j-config-spring-boot-1x-starter/src/main/java/cn/hippo4j/config/springboot1x/starter/web/jetty/JettyWebThreadPoolHandler1x.java new file mode 100644 index 00000000..be7bac20 --- /dev/null +++ b/hippo4j-spring-boot/hippo4j-config-spring-boot-1x-starter/src/main/java/cn/hippo4j/config/springboot1x/starter/web/jetty/JettyWebThreadPoolHandler1x.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.hippo4j.config.springboot1x.starter.web.jetty; + +import cn.hippo4j.adapter.web.IWebThreadPoolHandlerSupport; +import cn.hippo4j.adapter.web.jetty.JettyWebThreadPoolHandlerSupport; +import cn.hippo4j.common.enums.WebContainerEnum; +import cn.hippo4j.common.model.ThreadPoolBaseInfo; +import cn.hippo4j.common.model.ThreadPoolParameter; +import cn.hippo4j.common.model.ThreadPoolParameterInfo; +import cn.hippo4j.common.model.ThreadPoolRunStateInfo; +import cn.hippo4j.common.web.exception.ServiceException; +import cn.hippo4j.config.springboot1x.starter.web.AbstractWebThreadPoolService1x; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainer; + +import java.util.concurrent.Executor; + +/** + * WebThreadPoolHandler compatible with Jetty container for Spring 1.x version. + */ +@Slf4j +public class JettyWebThreadPoolHandler1x extends AbstractWebThreadPoolService1x { + + public JettyWebThreadPoolHandler1x() { + super(new JettyWebThreadPoolHandlerSupport()); + } + + @Override + protected Executor getWebThreadPoolInternal() { + try { + return ((JettyEmbeddedServletContainer) getContainer()).getServer().getThreadPool(); + } catch (Throwable th) { + log.error("Failed to get Jetty thread pool.", th); + return null; + } + } + +} diff --git a/hippo4j-spring-boot/hippo4j-config-spring-boot-1x-starter/src/main/java/cn/hippo4j/config/springboot1x/starter/web/tomcat/TomcatWebThreadPoolHandler1x.java b/hippo4j-spring-boot/hippo4j-config-spring-boot-1x-starter/src/main/java/cn/hippo4j/config/springboot1x/starter/web/tomcat/TomcatWebThreadPoolHandler1x.java new file mode 100644 index 00000000..614c8ecf --- /dev/null +++ b/hippo4j-spring-boot/hippo4j-config-spring-boot-1x-starter/src/main/java/cn/hippo4j/config/springboot1x/starter/web/tomcat/TomcatWebThreadPoolHandler1x.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.hippo4j.config.springboot1x.starter.web.tomcat; + +import cn.hippo4j.adapter.web.IWebThreadPoolHandlerSupport; +import cn.hippo4j.adapter.web.tomcat.TomcatWebThreadPoolHandlerSupport; +import cn.hippo4j.common.enums.WebContainerEnum; +import cn.hippo4j.common.model.ThreadPoolBaseInfo; +import cn.hippo4j.common.model.ThreadPoolParameter; +import cn.hippo4j.common.model.ThreadPoolParameterInfo; +import cn.hippo4j.common.model.ThreadPoolRunStateInfo; +import cn.hippo4j.common.web.exception.ServiceException; +import cn.hippo4j.config.springboot1x.starter.web.AbstractWebThreadPoolService1x; +import cn.hippo4j.core.executor.state.AbstractThreadPoolRuntime; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer; + +import java.util.concurrent.Executor; + +/** + * WebThreadPoolHandler compatible with Tomcat container for Spring 1.x version. + */ +@Slf4j +public class TomcatWebThreadPoolHandler1x extends AbstractWebThreadPoolService1x { + + public TomcatWebThreadPoolHandler1x(AbstractThreadPoolRuntime runtime) { + super(new TomcatWebThreadPoolHandlerSupport(runtime)); + } + + @Override + protected Executor getWebThreadPoolInternal() { + try { + return ((TomcatEmbeddedServletContainer) getContainer()) + .getTomcat().getConnector().getProtocolHandler().getExecutor(); + } catch (Throwable th) { + log.error("Failed to get Tomcat thread pool.", th); + return null; + } + } + +} diff --git a/hippo4j-spring-boot/hippo4j-config-spring-boot-1x-starter/src/main/java/cn/hippo4j/config/springboot1x/starter/web/undertow/UndertowWebThreadPoolHandler1x.java b/hippo4j-spring-boot/hippo4j-config-spring-boot-1x-starter/src/main/java/cn/hippo4j/config/springboot1x/starter/web/undertow/UndertowWebThreadPoolHandler1x.java new file mode 100644 index 00000000..c44a8e95 --- /dev/null +++ b/hippo4j-spring-boot/hippo4j-config-spring-boot-1x-starter/src/main/java/cn/hippo4j/config/springboot1x/starter/web/undertow/UndertowWebThreadPoolHandler1x.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.hippo4j.config.springboot1x.starter.web.undertow; + +import cn.hippo4j.adapter.web.IWebThreadPoolHandlerSupport; +import cn.hippo4j.adapter.web.undertow.UndertowWebThreadPoolHandlerSupport; +import cn.hippo4j.common.enums.WebContainerEnum; +import cn.hippo4j.common.model.ThreadPoolBaseInfo; +import cn.hippo4j.common.model.ThreadPoolParameter; +import cn.hippo4j.common.model.ThreadPoolParameterInfo; +import cn.hippo4j.common.model.ThreadPoolRunStateInfo; +import cn.hippo4j.common.web.exception.ServiceException; +import cn.hippo4j.config.springboot1x.starter.web.AbstractWebThreadPoolService1x; +import io.undertow.Undertow; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.context.embedded.undertow.UndertowEmbeddedServletContainer; +import org.springframework.util.ReflectionUtils; + +import java.lang.reflect.Field; +import java.util.concurrent.Executor; + +/** + * WebThreadPoolHandler compatible with Undertow container for Spring 1.x version. + */ +@Slf4j +public class UndertowWebThreadPoolHandler1x extends AbstractWebThreadPoolService1x { + + private static final String UNDERTOW_NAME = "undertow"; + + public UndertowWebThreadPoolHandler1x() { + super(new UndertowWebThreadPoolHandlerSupport()); + } + + @Override + protected Executor getWebThreadPoolInternal() { + try { + UndertowEmbeddedServletContainer container = (UndertowEmbeddedServletContainer) getContainer(); + Field field = ReflectionUtils.findField(UndertowEmbeddedServletContainer.class, UNDERTOW_NAME); + ReflectionUtils.makeAccessible(field); + Undertow undertow = (Undertow) ReflectionUtils.getField(field, container); + return undertow.getWorker(); + } catch (Throwable th) { + log.error("Failed to get Undertow thread pool.", th); + return null; + } + } + +} diff --git a/hippo4j-spring-boot/hippo4j-config-spring-boot-1x-starter/src/main/resources/META-INF/spring.factories b/hippo4j-spring-boot/hippo4j-config-spring-boot-1x-starter/src/main/resources/META-INF/spring.factories index 2fcd64db..9c1405c6 100644 --- a/hippo4j-spring-boot/hippo4j-config-spring-boot-1x-starter/src/main/resources/META-INF/spring.factories +++ b/hippo4j-spring-boot/hippo4j-config-spring-boot-1x-starter/src/main/resources/META-INF/spring.factories @@ -1 +1,3 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=cn.hippo4j.config.springboot1x.starter.config.ConfigHandlerAutoConfiguration +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ + cn.hippo4j.config.springboot1x.starter.config.ConfigHandlerAutoConfiguration,\ + cn.hippo4j.config.springboot1x.starter.config.WebThreadPoolHandlerConfiguration1x \ No newline at end of file diff --git a/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/config/springboot/starter/refresher/event/WebExecutorRefreshListener.java b/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/config/springboot/starter/refresher/event/WebExecutorRefreshListener.java index e7c2a269..a7f9e60d 100644 --- a/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/config/springboot/starter/refresher/event/WebExecutorRefreshListener.java +++ b/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/config/springboot/starter/refresher/event/WebExecutorRefreshListener.java @@ -28,6 +28,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.core.annotation.Order; import java.util.Objects; +import java.util.Optional; import static cn.hippo4j.config.springboot.starter.refresher.event.Hippo4jConfigDynamicRefreshEventOrder.WEB_EXECUTOR_LISTENER; @@ -55,6 +56,17 @@ public class WebExecutorRefreshListener extends AbstractRefreshListener