在Spring Boot的 WebFlux中,嵌入式服务器的Reactor Netty设置应如何调整,与Tomcat相比有哪些差异?
我有一个关于在使用Reactor Netty的 Spring Boot + Spring WebFlux应用中嵌入式服务器配置的问题。
在传统的Spring MVC +嵌入式Tomcat环境中,我理解可以通过设置server.tomcat.threads.max、server.tomcat.max-connections和 server.tomcat.accept-count来控制Tomcat工作线程池大小、最大连接数和接受队列等。
然而,当使用Spring WebFlux,默认嵌入式服务器是Reactor Netty时,请求处理模型与Tomcat的逐请求线程模型不同。因此,我想更清楚地了解应该考虑哪些设置,以及如何解读它们。
当前应用使用spring-boot-starter-webflux,数据库访问通过R2DBC连接池处理。
环境:
Spring Boot: 3.5.11
Spring Framework: 6.2.16
Reactor Netty: 1.2.15
Java: 17
Database: Microsoft SQL Server
R2DBC driver: io.r2dbc:r2dbc-mssql 1.0.4.RELEASE
R2DBC pool: io.r2dbc:r2dbc-pool 1.0.2.RELEASE
R2DBC pool max-size: 50
下面是当前配置的一个示例:
server.port=30003
spring.r2dbc.pool.enabled=true
spring.r2dbc.pool.initial-size=10
spring.r2dbc.pool.max-size=50
spring.r2dbc.pool.max-acquire-time=10s
spring.r2dbc.pool.max-create-connection-time=5s
spring.r2dbc.pool.max-idle-time=30m
spring.r2dbc.pool.max-life-time=60m
spring.r2dbc.pool.validation-query=SELECT 1
使用JMeter进行负载测试,JMeter端开启了HTTP Keep-Alive。
在负载测试过程中,观察到以下错误:
java.net.SocketException: Socket Closed
java.net.SocketException: Socket operation on nonsocket: connect
org.springframework.dao.DataAccessResourceFailureException: Failed to obtain R2DBC Connection
我想了解这些错误更可能与服务器端的连接/线程相关限制、R2DBC连接池耗尽、数据库端的连接或锁定限制,还是在JMeter/客户端环境中的套接字资源限制有关。
我的问题如下:
-
在Spring Boot WebFlux + Reactor Netty环境中,处理HTTP请求所使用的事件循环线程数量默认是如何确定的?
-
是否存在在概念上对应Tomcat的 server.tomcat.threads.max、server.tomcat.max-connections、server.tomcat.accept-count的 Reactor Netty或 Spring Boot设置?
如果存在这样的设置,应该使用哪些属性或自定义器?
如果没有直接等价的设置,在WebFlux应用中应如何限制或控制并发请求数或并发连接数?
- 在Spring Boot WebFlux应用中,应该将请求处理超时、连接超时、空闲超时和响应超时等超时值配置在哪里?
例如,应该通过server.netty.connection-timeout、NettyReactiveWebServerFactory、NettyServerCustomizer,还是通过Reactor Netty的 HttpServer自定义器来配置?
- 应如何分开分析HTTP服务器调优和R2DBC连接池调优?
例如,如果把HTTP连接数上限提高,但R2DBC池的最大大小为50,那么可以理解为数据库密集型API仍然会受到R2DBC池、数据库服务器或数据库锁的瓶颈吗?
- 在高并发场景下使用r2dbc-mssql和 r2dbc-pool与 Spring Boot WebFlux相关的已知注意事项或限制有哪些?
我的理解是,WebFlux不使用与Tomcat相同的逐请求线程模型,而是使用基于事件循环的Reactor Netty的非阻塞模型。因此,我不应把“工作线程数”理解为与Tomcat中的“最大并发请求数”相同的概念。
如果能就Spring Boot WebFlux + Reactor Netty的服务器端调优建议、如何检查默认值、以及哪些Tomcat概念不应直接映射到Reactor Netty/WebFlux,给予指导,我将不胜感激。
谢谢。
解决方案
只做一件事
server.port=30005
spring.r2dbc.pool.enabled=true
spring.r2dbc.pool.initial-size=20
spring.r2dbc.pool.max-size=10
spring.r2dbc.pool.max-acquire-time=10s
spring.r2dbc.pool.max-create-connection-time=10s
spring.r2dbc.pool.max-idle-time=30m
spring.r2dbc.pool.max-life-time=60m
spring.r2dbc.pool.validation-query=SELECT 1