使用 Tomcat 和 Springboot 配置 HTTPS 时,异步支持被禁用

async-supported gets disabled when configuring HTTPS with Tomcat and Springboot

我目前正在开发启用了 tomcat 和 HTTPS 的 Springboot 2.1 应用程序。我们正在尝试使用 spring-webflux 提供的新 Reactive 堆栈编写一些新的 APIs。由于应用程序仍然具有传统的阻塞端点,我们需要使用 Tomcat 并启用异步支持以使新的非阻塞 APIs 工作。

当 运行 API 并尝试通过 HTTPS 访问端点时,我收到以下错误:

ERROR c.b.b.c.u.s.r.c.ApiExceptionHandler - Async support must be enabled on a servlet and for all filters involved in async request processing. This is done in Java code using the Servlet API or by adding "<async-supported>true</async-supported>" to servlet and filter declarations in web.xml.
java.lang.IllegalStateException: Async support must be enabled on a servlet and for all filters involved in async request processing. This is done in Java code using the Servlet API or by adding "<async-supported>true</async-supported>" to servlet and filter declarations in web.xml.

如果我禁用 HTTPS 并使用 HTTP 访问 API,则请求有效并且我从新的非阻塞 API 控制器获得响应。

目前使用以下代码配置 HTTPS(如果我删除此配置,非阻塞 api 有效):

@Configuration
public class Config implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> {

    private final SslProperties sslProperties;
    private final LogbackAccessProperties logbackAccessProperties;

    public BootConfig(SslProperties sslProperties, LogbackAccessProperties logbackAccessProperties) {
        this.sslProperties = sslProperties;
        this.logbackAccessProperties = logbackAccessProperties;
    }

    @Override
    public void customize(TomcatServletWebServerFactory factory) {
        factory.addContextValves(getLogbackValve());
        factory.addConnectorCustomizers(connector -> {
            Http11NioProtocol proto = (Http11NioProtocol) connector.getProtocolHandler();
            proto.setSSLEnabled(true);
            connector.setScheme("https");
            connector.setSecure(true);
            proto.setKeystoreFile(sslProperties.getKeyStoreLocation());
            proto.setKeystorePass(sslProperties.getKeyStorePassword());
            proto.setKeystoreType(sslProperties.getKeyStoreType());
            proto.setTruststoreFile(sslProperties.getKeyStoreLocation());
            proto.setTruststorePass(sslProperties.getKeyStorePassword());
            proto.setTruststoreType(sslProperties.getKeyStoreType());
            proto.setKeyAlias(sslProperties.getHostingServerKeyAlias());
            proto.setSslEnabledProtocols("TLSv1.2");
        });
    }

    private LogbackValve getLogbackValve() {
        LogbackValve valve = new LogbackValve();
        valve.setFilename(logbackAccessProperties.getConfig());
        return valve;
    }
}

在线阅读 我可以看到 Springboot 在使用 tomcat 和 spring-boot-starter-webflux 时默认启用 async-supportedspring-mvc。这似乎是使用 HTTP 时的情况,但设置 HTTPS 时似乎不再起作用。在设置 HTTPS 时是否有另一种启用它的方法?

我最终找到了问题的原因。使用 HTTPS 不会导致问题。我相信情况就是这样,因为当我删除 public void customize(TomcatServletWebServerFactory factory) {... 方法时它起作用了。

似乎正在添加的 LogbackValve 禁用了异步。阀门需要设置 asyncSupported=true 才能工作。所以我不得不将我的方法更新为:

    private LogbackValve getLogbackValve() {
        LogbackValve valve = new LogbackValve();
        valve.setFilename(logbackAccessProperties.getConfig());
        valve.setAsyncSupported(true); // This line fixed the issue
        return valve;
    }

从阅读文档来看,这不是很明显,所以我花了一些时间才弄明白。如果有人遇到同样的问题,我希望它能有所帮助 :)