如何使用Spring Boot和嵌入式Tomcat配置此属性?

13

我应该在application.properties文件中配置连接超时等属性,还是有其他更好的方式?我在谷歌上找不到答案。

Tomcat属性列表

我找到了这个Spring-Boot示例,但它没有包含connectionTimeout属性。当我在application.properties文件中设置server.tomcat.connectionTimeout=60000时,出现错误。


org.springframework.beans.factory.BeanCreationException:创建名为'tomcatEbeddedServletContainerFactory'的bean时出错... Bean属性'connectionTimeout'不可写或具有无效的setter方法。 - smuggledPancakes
4个回答

28

Spring Boot 1.4及以上版本

从Spring Boot 1.4开始,您可以使用属性server.connection-timeout。请参见Spring Boot的常用应用程序属性

Spring Boot 1.3及更早版本

提供一个自定义的EmbeddedServletContainerFactory bean:

@Bean
public EmbeddedServletContainerFactory servletContainerFactory() {
    TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();

    factory.addConnectorCustomizers(connector -> 
            ((AbstractProtocol) connector.getProtocolHandler()).setConnectionTimeout(10000));

    // configure some more properties

    return factory;
}

如果您不使用Java 8或不想使用Lambda表达式,请按照以下方式添加TomcatConnectorCustomizer:
    factory.addConnectorCustomizers(new TomcatConnectorCustomizer() {
        @Override
        public void customize(Connector connector) {
            ((AbstractProtocol) connector.getProtocolHandler()).setConnectionTimeout(10000);
        }
    });
< p > setConnectionTimeout() 方法期望以毫秒为单位的超时时间(请参见 Apache Tomcat 8 配置参考 中的 connectionTimeout)。< /p >

我不想创建一个新的TomcatEmbeddedServletContainerFactory,有没有一种方法可以只更改现有的配置?那个方法应该放在哪里? - smuggledPancakes
1
我不完全确定它是否有效,但你可以尝试像Spring Boot一样做:使用@ConditionalOnClass({ Servlet.class, Tomcat.class })注释生成EmbeddedServletContainerFactory bean的@Configuration类。请参见EmbeddedServletContainerAutoConfiguration - hzpz
看起来 @ConditionalOnClass({ Servlet.class, Tomcat.class }) 对我的 WAR 有效。我无意中包含了我的 Tomcat 配置类,它依赖于 tomcat-embed 中的一个类,但当我运行部署的 WAR 时,它并没有崩溃。我修复了我的 ant 文件以排除 Tomcat 配置类,我根本不想在 WAR 中包含它。 - smuggledPancakes
谢谢更新!我会自己测试@ConditionalOnClass的。现在让我们把它放在评论中。 - hzpz
我有一个几乎相同的问题,但是针对的是在连接器上设置maxSwallowSize(我想这是在Tomcat 8.0.9中引入的)。我还没有找到包含该属性的类。你有什么想法吗?(如果这是一个完全不同的属性,我会开一个新的问题) - Jim
显示剩余8条评论

4

在服务器启动之前,我更喜欢设置系统属性的集合:

/**
 * Start SpringBoot server
 */
@SpringBootApplication(scanBasePackages= {"com.your.conf.package"})
//@ComponentScan(basePackages = "com.your.conf.package")
public class Application {
    public static void main(String[] args) throws Exception {
        System.setProperty("server.port","8132"));
        System.setProperty("server.tomcat.max-threads","200");
        System.setProperty("server.connection-timeout","60000");
        ApplicationContext ctx = SpringApplication.run(Application.class, args);
    }
}

这个解决方案对我非常完美地起作用了:https://gist.github.com/vishwaraja/24f2935cad4b59ca2e85dc08368e120f - user1807948
1
“server.tomcat.max-threads” 的值设为 “200” 是否过高?它应该降低到两位数,例如 “50” 或类似的数字吗?我正在尝试理解什么是适合 “max-threads” 的好数字。 - SGB

3
在Spring Boot 2.x及以后版本中,嵌入式Tomcat的实现方法已经发生了变化。
请参考以下代码。

Original Answer:最初的回答。

import org.apache.coyote.http11.AbstractHttp11Protocol;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Configuration;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Configuration
public class TomcatCustomizer implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> {

    @Autowired
    private ContainerProperties containerProperties;

    @Override
    public void customize(TomcatServletWebServerFactory factory) {
        factory.addConnectorCustomizers(connector -> {
            AbstractHttp11Protocol protocol = (AbstractHttp11Protocol) connector.getProtocolHandler();

            protocol.setMaxKeepAliveRequests(10);


            log.info("####################################################################################");
            log.info("#");
            log.info("# TomcatCustomizer");
            log.info("#");
            log.info("# custom maxKeepAliveRequests {}", protocol.getMaxKeepAliveRequests());
            log.info("# origin keepalive timeout: {} ms", protocol.getKeepAliveTimeout());
            log.info("# keepalive timeout: {} ms", protocol.getKeepAliveTimeout());
            log.info("# connection timeout: {} ms", protocol.getConnectionTimeout());
            log.info("# max connections: {}", protocol.getMaxConnections());
            log.info("#");
            log.info(
                "####################################################################################");

        });
    }
}

1

实际上应该在你的application.properties文件中设置server.connection-timeout参考文献,我建议你将其加入书签。


7
使用 server.connection-timeout 属性时,必须指定单位,否则不会生效。例如,您可以使用 server.connection-timeout=5000msserver.connection-timeout=5s 来设置 5 秒的超时时间。但是您不能只写 server.connection-timeout=5000,这是无效的。 - MiguelMunoz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接