Spring Boot 独立配置 actuator(management) 线程池大小

660 阅读1分钟

问题描述

  1. 使用Spring boot 时,如果打开了management 端口,则tomcat 会启动两个线程池,分别处理来自两个端口的请求
  2. 通常我们会使用server.tomcat.threads 自定义线程池大小,以满足业务的处理需求;而此时management 会复用此配置,配置management的线程池大小
  3. 通常management 是管理端口,请求量极少,线程需求少;而server.port 的业务端口因承载业务请求,线程需求大,此时共享同一个配置会造成线程池资源的浪费

解决方式

  1. SpringBoot 在初始化management 的context 时,不会扫描项目中的自定义Configuration或者ManagementContextConfiguration 定义的class,导致其线程池无法自定义
  2. 可以在META-INFO/spring.factories文件中配置org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration=xxx 的方式自定义配置类
  3. 此配置类需要通过jar包依赖的方式加入到项目中,spring boot 启动时会自动扫描该文件,并加载其定义的class
class

@ManagementContextConfiguration
public class TomcatManagementCustomizerConfiguration {
    private static final Log log = LogFactory.getLog(TomcatManagementCustomizerConfiguration.class);

    @Bean
    ManagementWebServerFactoryCustomizer<ConfigurableServletWebServerFactory> servletManagementWebServerFactoryCustomizer(
            @Value("${management.server.threads.min-spare:5}") int managementMinSpareThreads,
            @Value("${management.server.threads.max-threads:5}") int managementMaxThreads,
            @Value("${management.server.accept-count:5}") int managementAcceptCount,
            ListableBeanFactory beanFactory) {
        log.info("TomcatManagementCustomizerConfiguration init..");
        if (managementMinSpareThreads > managementMaxThreads) {
            managementMinSpareThreads = managementMaxThreads;
        }
        return new TomcatManagementCustomizer(beanFactory, managementMinSpareThreads, managementMaxThreads, managementAcceptCount);
    }

    static class TomcatManagementCustomizer extends ManagementWebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {
        private final int managementMinSpareThreads;
        private final int managementMaxThreads;
        private final int managementAcceptCount;

        protected TomcatManagementCustomizer(ListableBeanFactory beanFactory, int managementMinSpareThreads
                , int managementMaxThreads, int managementAcceptCount) {
            super(beanFactory, TomcatWebServerFactoryCustomizer.class);
            this.managementMinSpareThreads = managementMinSpareThreads;
            this.managementMaxThreads = managementMaxThreads;
            this.managementAcceptCount = managementAcceptCount;
        }

        @Override
        @SuppressWarnings("rawtypes")
        protected void customize(ConfigurableServletWebServerFactory factory, ManagementServerProperties managementServerProperties, ServerProperties serverProperties) {
            super.customize(factory, managementServerProperties, serverProperties);
            ((TomcatServletWebServerFactory) factory).addConnectorCustomizers((connector) -> {
                ProtocolHandler handler = connector.getProtocolHandler();
                if (handler instanceof AbstractProtocol) {
                    AbstractProtocol protocol = (AbstractProtocol) handler;
                    protocol.setMinSpareThreads(managementMinSpareThreads);
                    protocol.setMaxThreads(managementMaxThreads);
                    protocol.setAcceptCount(managementAcceptCount);
                    log.info("TomcatManagementCustomizerConfiguration custom for port:" + protocol.getPort() + ", managementMinSpareThreads:" + managementMinSpareThreads
                            + ", managementMaxThreads:" + managementMaxThreads + ", managementAcceptCount:" + managementAcceptCount);
                }
            });
        }
    }
}