diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/nested/ServletConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/nested/ServletConfig.java index 6bcbe50b609..d87938c5507 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/config/nested/ServletConfig.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/config/nested/ServletConfig.java @@ -28,6 +28,14 @@ public class ServletConfig implements Serializable { */ private Boolean enabled; + /** + * Maximum concurrent streams. + *

For HTTP/2 + *

Note that the default value for tomcat is 20. Highly recommended to change it to {@link Integer#MAX_VALUE} + *

If set to zero or a negative number, the actual value will be set to {@link Integer#MAX_VALUE}. + */ + private Integer maxConcurrentStreams; + /** * The URL patterns that the servlet filter will be registered for. *

The default value is '/*'. @@ -48,6 +56,14 @@ public void setEnabled(Boolean enabled) { this.enabled = enabled; } + public Integer getMaxConcurrentStreams() { + return maxConcurrentStreams; + } + + public void setMaxConcurrentStreams(Integer maxConcurrentStreams) { + this.maxConcurrentStreams = maxConcurrentStreams; + } + public String[] getFilterUrlPatterns() { return filterUrlPatterns; } diff --git a/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/pom.xml b/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/pom.xml index e65cf6bf5fd..07ec5b92a4a 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/pom.xml +++ b/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/pom.xml @@ -70,7 +70,12 @@ jakarta.servlet jakarta.servlet-api - true + provided + + + org.apache.tomcat.embed + tomcat-embed-core + provided diff --git a/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTriple3AutoConfiguration.java b/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTriple3AutoConfiguration.java index 6b03e6be7d0..8caac7a29a7 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTriple3AutoConfiguration.java +++ b/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTriple3AutoConfiguration.java @@ -20,11 +20,16 @@ import org.apache.dubbo.rpc.protocol.tri.servlet.jakarta.TripleFilter; import jakarta.servlet.Filter; +import org.apache.coyote.ProtocolHandler; +import org.apache.coyote.UpgradeProtocol; +import org.apache.coyote.http2.Http2Protocol; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; +import org.springframework.boot.web.embedded.tomcat.ConfigurableTomcatWebServerFactory; +import org.springframework.boot.web.server.WebServerFactoryCustomizer; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; @@ -39,7 +44,7 @@ public class DubboTriple3AutoConfiguration { @Configuration(proxyBeanMethods = false) @ConditionalOnClass(Filter.class) @ConditionalOnWebApplication(type = Type.SERVLET) - @ConditionalOnProperty(prefix = PREFIX, name = "enabled") + @ConditionalOnProperty(prefix = PREFIX, name = "enabled", havingValue = "true") public static class TripleServletConfiguration { @Bean @@ -54,5 +59,23 @@ public FilterRegistrationBean tripleProtocolFilter( registrationBean.setOrder(order); return registrationBean; } + + @Bean + @ConditionalOnClass(Http2Protocol.class) + @ConditionalOnProperty(prefix = PREFIX, name = "max-concurrent-streams") + public WebServerFactoryCustomizer tripleTomcatHttp2Customizer( + @Value("${" + PREFIX + ".max-concurrent-streams}") int maxConcurrentStreams) { + return factory -> factory.addConnectorCustomizers(connector -> { + ProtocolHandler handler = connector.getProtocolHandler(); + for (UpgradeProtocol upgradeProtocol : handler.findUpgradeProtocols()) { + if (upgradeProtocol instanceof Http2Protocol) { + Http2Protocol protocol = (Http2Protocol) upgradeProtocol; + int value = maxConcurrentStreams <= 0 ? Integer.MAX_VALUE : maxConcurrentStreams; + protocol.setMaxConcurrentStreams(value); + protocol.setMaxConcurrentStreamExecution(value); + } + } + }); + } } } diff --git a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/pom.xml b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/pom.xml index 7e3b19cb4e0..5f9ebd3daf1 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/pom.xml +++ b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/pom.xml @@ -83,6 +83,11 @@ javax.servlet-api provided + + org.apache.tomcat.embed + tomcat-embed-core + provided + diff --git a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTripleAutoConfiguration.java b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTripleAutoConfiguration.java index 16f21dfef8d..3dfecdb9529 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTripleAutoConfiguration.java +++ b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTripleAutoConfiguration.java @@ -21,11 +21,16 @@ import javax.servlet.Filter; +import org.apache.coyote.ProtocolHandler; +import org.apache.coyote.UpgradeProtocol; +import org.apache.coyote.http2.Http2Protocol; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; +import org.springframework.boot.web.embedded.tomcat.ConfigurableTomcatWebServerFactory; +import org.springframework.boot.web.server.WebServerFactoryCustomizer; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; @@ -40,7 +45,7 @@ public class DubboTripleAutoConfiguration { @Configuration(proxyBeanMethods = false) @ConditionalOnClass(Filter.class) @ConditionalOnWebApplication(type = Type.SERVLET) - @ConditionalOnProperty(prefix = PREFIX, name = "enabled") + @ConditionalOnProperty(prefix = PREFIX, name = "enabled", havingValue = "true") public static class TripleServletConfiguration { @Bean @@ -55,5 +60,23 @@ public FilterRegistrationBean tripleProtocolFilter( registrationBean.setOrder(order); return registrationBean; } + + @Bean + @ConditionalOnClass(Http2Protocol.class) + @ConditionalOnProperty(prefix = PREFIX, name = "max-concurrent-streams") + public WebServerFactoryCustomizer tripleTomcatHttp2Customizer( + @Value("${" + PREFIX + ".max-concurrent-streams}") int maxConcurrentStreams) { + return factory -> factory.addConnectorCustomizers(connector -> { + ProtocolHandler handler = connector.getProtocolHandler(); + for (UpgradeProtocol upgradeProtocol : handler.findUpgradeProtocols()) { + if (upgradeProtocol instanceof Http2Protocol) { + Http2Protocol protocol = (Http2Protocol) upgradeProtocol; + int value = maxConcurrentStreams <= 0 ? Integer.MAX_VALUE : maxConcurrentStreams; + protocol.setMaxConcurrentStreams(value); + protocol.setMaxConcurrentStreamExecution(value); + } + } + }); + } } }