add jetty、undertow ThreadPool

pull/117/head
weihu 3 years ago
parent 2587e71983
commit d7c17f9a2c

@ -26,6 +26,20 @@
<artifactId>spring-boot-starter-web</artifactId> <artifactId>spring-boot-starter-web</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency> <dependency>
<groupId>com.squareup.okhttp3</groupId> <groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId> <artifactId>okhttp</artifactId>

@ -17,9 +17,7 @@ import cn.hippo4j.starter.event.ApplicationContentPostProcessor;
import cn.hippo4j.starter.handler.BaseThreadDetailStateHandler; import cn.hippo4j.starter.handler.BaseThreadDetailStateHandler;
import cn.hippo4j.starter.handler.DynamicThreadPoolBannerHandler; import cn.hippo4j.starter.handler.DynamicThreadPoolBannerHandler;
import cn.hippo4j.starter.handler.ThreadPoolRunStateHandler; import cn.hippo4j.starter.handler.ThreadPoolRunStateHandler;
import cn.hippo4j.starter.handler.web.TomcatWebThreadPoolHandler; import cn.hippo4j.starter.handler.web.*;
import cn.hippo4j.starter.handler.web.WebThreadPoolHandlerChoose;
import cn.hippo4j.starter.handler.web.WebThreadPoolRunStateHandler;
import cn.hippo4j.starter.monitor.ReportingEventExecutor; import cn.hippo4j.starter.monitor.ReportingEventExecutor;
import cn.hippo4j.starter.monitor.collect.RunTimeInfoCollector; import cn.hippo4j.starter.monitor.collect.RunTimeInfoCollector;
import cn.hippo4j.starter.monitor.send.HttpConnectSender; import cn.hippo4j.starter.monitor.send.HttpConnectSender;
@ -28,13 +26,11 @@ import cn.hippo4j.starter.remote.HttpAgent;
import cn.hippo4j.starter.remote.HttpScheduledHealthCheck; import cn.hippo4j.starter.remote.HttpScheduledHealthCheck;
import cn.hippo4j.starter.remote.ServerHealthCheck; import cn.hippo4j.starter.remote.ServerHealthCheck;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration; import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered; import org.springframework.core.Ordered;
@ -55,6 +51,12 @@ import org.springframework.core.env.ConfigurableEnvironment;
@ImportAutoConfiguration({HttpClientConfiguration.class, DiscoveryConfiguration.class, MessageNotifyConfiguration.class, UtilAutoConfiguration.class}) @ImportAutoConfiguration({HttpClientConfiguration.class, DiscoveryConfiguration.class, MessageNotifyConfiguration.class, UtilAutoConfiguration.class})
public class DynamicThreadPoolAutoConfiguration { public class DynamicThreadPoolAutoConfiguration {
private static final String TOMCAT_SERVLET_WEB_SERVER_FACTORY = "tomcatWebThreadPoolHandler";
private static final String JETTY_SERVLET_WEB_SERVER_FACTORY = "JettyServletWebServerFactory";
private static final String UNDERTOW_SERVLET_WEB_SERVER_FACTORY = "undertowServletWebServerFactory";
private final BootstrapProperties properties; private final BootstrapProperties properties;
private final ConfigurableEnvironment environment; private final ConfigurableEnvironment environment;
@ -143,11 +145,23 @@ public class DynamicThreadPoolAutoConfiguration {
} }
@Bean @Bean
@ConditionalOnBean(name = "tomcatServletWebServerFactory") @ConditionalOnBean(name = TOMCAT_SERVLET_WEB_SERVER_FACTORY)
public TomcatWebThreadPoolHandler tomcatWebThreadPoolHandler(@Autowired(required = false) ServletWebServerApplicationContext applicationContext) { public TomcatWebThreadPoolHandler tomcatWebThreadPoolHandler() {
return new TomcatWebThreadPoolHandler(applicationContext); return new TomcatWebThreadPoolHandler();
}
@Bean
@ConditionalOnBean(name = JETTY_SERVLET_WEB_SERVER_FACTORY)
public JettyWebThreadPoolHandler jettyWebThreadPoolHandler() {return new JettyWebThreadPoolHandler();
} }
@Bean
@ConditionalOnBean(name = UNDERTOW_SERVLET_WEB_SERVER_FACTORY)
public UndertowWebThreadPoolHandler undertowWebThreadPoolHandler() {
return new UndertowWebThreadPoolHandler();
}
@Bean @Bean
public WebThreadPoolHandlerChoose webThreadPoolServiceChoose() { public WebThreadPoolHandlerChoose webThreadPoolServiceChoose() {
return new WebThreadPoolHandlerChoose(); return new WebThreadPoolHandlerChoose();

@ -1,5 +1,14 @@
package cn.hippo4j.starter.handler.web; package cn.hippo4j.starter.handler.web;
import cn.hippo4j.common.config.ApplicationContextHolder;
import cn.hippo4j.common.model.PoolParameterInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.context.WebServerApplicationContext;
import org.springframework.boot.web.server.WebServer;
import org.springframework.boot.web.servlet.context.ServletWebServerInitializedEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
/** /**
@ -8,6 +17,7 @@ import java.util.concurrent.Executor;
* @author chen.ma * @author chen.ma
* @date 2022/1/19 21:20 * @date 2022/1/19 21:20
*/ */
@Slf4j
public abstract class AbstractWebThreadPoolService implements WebThreadPoolService { public abstract class AbstractWebThreadPoolService implements WebThreadPoolService {
/** /**
@ -20,14 +30,18 @@ public abstract class AbstractWebThreadPoolService implements WebThreadPoolServi
* *
* @return * @return
*/ */
protected abstract Executor getWebThreadPoolByServer(); protected abstract Executor getWebThreadPoolByServer(WebServer webServer);
@Override @Override
public Executor getWebThreadPool() { public Executor getWebThreadPool() {
if (executor == null) { if (executor == null) {
synchronized (AbstractWebThreadPoolService.class) { synchronized (AbstractWebThreadPoolService.class) {
ApplicationContext applicationContext = ApplicationContextHolder.getInstance();
WebServer webServer = ((WebServerApplicationContext) applicationContext).getWebServer();
if (executor == null) { if (executor == null) {
executor = getWebThreadPoolByServer(); executor = getWebThreadPoolByServer(webServer);
} }
} }
} }

@ -0,0 +1,51 @@
package cn.hippo4j.starter.handler.web;
import cn.hippo4j.common.model.PoolParameterInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.embedded.jetty.JettyWebServer;
import org.springframework.boot.web.server.WebServer;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* @author : wh
* @date : 2022/2/28 16:55
* @description:
*/
@Slf4j
public class JettyWebThreadPoolHandler extends AbstractWebThreadPoolService{
@Override
protected Executor getWebThreadPoolByServer(WebServer webServer) {
JettyWebServer jettyWebServer = (JettyWebServer) webServer;
return jettyWebServer.getServer().getThreadPool();
}
@Override
public void updateWebThreadPool(PoolParameterInfo poolParameterInfo) {
try {
ThreadPoolExecutor jettyExecutor = (ThreadPoolExecutor) executor;
int originalCoreSize = jettyExecutor.getCorePoolSize();
int originalMaximumPoolSize = jettyExecutor.getMaximumPoolSize();
long originalKeepAliveTime = jettyExecutor.getKeepAliveTime(TimeUnit.SECONDS);
jettyExecutor.setCorePoolSize(poolParameterInfo.getCoreSize());
jettyExecutor.setMaximumPoolSize(poolParameterInfo.getMaxSize());
jettyExecutor.setKeepAliveTime(poolParameterInfo.getKeepAliveTime(), TimeUnit.SECONDS);
log.info(
"🔥 Changed web thread pool. coreSize :: [{}], maxSize :: [{}], keepAliveTime :: [{}]",
String.format("%s => %s", originalCoreSize, poolParameterInfo.getCoreSize()),
String.format("%s => %s", originalMaximumPoolSize, poolParameterInfo.getMaxSize()),
String.format("%s => %s", originalKeepAliveTime, poolParameterInfo.getKeepAliveTime())
);
} catch (Exception ex) {
log.error("Failed to modify the jetty thread pool parameter.", ex);
}
}
}

@ -4,7 +4,7 @@ import cn.hippo4j.common.model.PoolParameterInfo;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.embedded.tomcat.TomcatWebServer; import org.springframework.boot.web.embedded.tomcat.TomcatWebServer;
import org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext; import org.springframework.boot.web.server.WebServer;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor;
@ -21,14 +21,13 @@ import java.util.concurrent.atomic.AtomicBoolean;
@AllArgsConstructor @AllArgsConstructor
public class TomcatWebThreadPoolHandler extends AbstractWebThreadPoolService{ public class TomcatWebThreadPoolHandler extends AbstractWebThreadPoolService{
private final ServletWebServerApplicationContext applicationContext;
private final AtomicBoolean cacheFlag = new AtomicBoolean(Boolean.FALSE); private final AtomicBoolean cacheFlag = new AtomicBoolean(Boolean.FALSE);
private static String EXCEPTION_MESSAGE; private static String EXCEPTION_MESSAGE;
@Override @Override
protected Executor getWebThreadPoolByServer() { protected Executor getWebThreadPoolByServer(WebServer webServer) {
if (cacheFlag.get()) { if (cacheFlag.get()) {
log.warn("Exception getting Tomcat thread pool. Exception message :: {}", EXCEPTION_MESSAGE); log.warn("Exception getting Tomcat thread pool. Exception message :: {}", EXCEPTION_MESSAGE);
return null; return null;
@ -36,7 +35,7 @@ public class TomcatWebThreadPoolHandler extends AbstractWebThreadPoolService {
Executor tomcatExecutor = null; Executor tomcatExecutor = null;
try { try {
tomcatExecutor = ((TomcatWebServer) applicationContext.getWebServer()).getTomcat().getConnector().getProtocolHandler().getExecutor(); tomcatExecutor = ((TomcatWebServer) webServer).getTomcat().getConnector().getProtocolHandler().getExecutor();
} catch (Exception ex) { } catch (Exception ex) {
cacheFlag.set(Boolean.TRUE); cacheFlag.set(Boolean.TRUE);
EXCEPTION_MESSAGE = ex.getMessage(); EXCEPTION_MESSAGE = ex.getMessage();

@ -1,10 +1,19 @@
package cn.hippo4j.starter.handler.web; package cn.hippo4j.starter.handler.web;
import cn.hippo4j.common.model.PoolParameterInfo; import cn.hippo4j.common.model.PoolParameterInfo;
import io.undertow.Undertow;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.embedded.undertow.UndertowWebServer;
import org.springframework.boot.web.server.WebServer;
import org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext; import org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext;
import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Field;
import java.util.Objects;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/** /**
* Undertow web thread pool handler. * Undertow web thread pool handler.
@ -12,18 +21,45 @@ import java.util.concurrent.Executor;
* @author chen.ma * @author chen.ma
* @date 2022/1/19 21:19 * @date 2022/1/19 21:19
*/ */
@AllArgsConstructor @Slf4j
public class UndertowWebThreadPoolHandler extends AbstractWebThreadPoolService { public class UndertowWebThreadPoolHandler extends AbstractWebThreadPoolService {
private final ServletWebServerApplicationContext applicationContext; private static final String UNDERTOW_NAME = "undertow";
@Override @Override
protected Executor getWebThreadPoolByServer() { protected Executor getWebThreadPoolByServer(WebServer webServer) {
return null; // There is no need to consider reflection performance because the fetch is a singleton
UndertowWebServer undertowWebServer = (UndertowWebServer) webServer;
Field undertowField = ReflectionUtils.findField(UndertowWebServer.class, UNDERTOW_NAME);
assert undertowField != null;
ReflectionUtils.makeAccessible(undertowField);
Undertow undertow = (Undertow) ReflectionUtils.getField(undertowField, undertowWebServer);
return Objects.isNull(undertow) ? null : undertow.getWorker();
} }
@Override @Override
public void updateWebThreadPool(PoolParameterInfo poolParameterInfo) { public void updateWebThreadPool(PoolParameterInfo poolParameterInfo) {
try {
ThreadPoolExecutor undertowExecutor = (ThreadPoolExecutor) executor;
int originalCoreSize = undertowExecutor.getCorePoolSize();
int originalMaximumPoolSize = undertowExecutor.getMaximumPoolSize();
long originalKeepAliveTime = undertowExecutor.getKeepAliveTime(TimeUnit.SECONDS);
undertowExecutor.setCorePoolSize(poolParameterInfo.getCoreSize());
undertowExecutor.setMaximumPoolSize(poolParameterInfo.getMaxSize());
undertowExecutor.setKeepAliveTime(poolParameterInfo.getKeepAliveTime(), TimeUnit.SECONDS);
log.info(
"🔥 Changed web thread pool. coreSize :: [{}], maxSize :: [{}], keepAliveTime :: [{}]",
String.format("%s => %s", originalCoreSize, poolParameterInfo.getCoreSize()),
String.format("%s => %s", originalMaximumPoolSize, poolParameterInfo.getMaxSize()),
String.format("%s => %s", originalKeepAliveTime, poolParameterInfo.getKeepAliveTime())
);
} catch (Exception ex) {
log.error("Failed to modify the undertow thread pool parameter.", ex);
}
} }

Loading…
Cancel
Save