Spring Boot虚拟线程(Tomcat)下如何限制Servlet请求并发数?
在Spring Boot 3.3+虚拟线程环境下限制最大并发请求数
针对你的场景,以下是两种实用的方案来限制并发请求数,避免数据库连接池耗尽:
方案一:配置Tomcat最大连接数
启用虚拟线程后,server.tomcat.threads.max仅控制Tomcat接收连接的平台线程池大小,不再能限制实际并发请求数。此时可以通过server.tomcat.max-connections直接限制Tomcat能处理的最大并发连接数,间接控制并发请求量:
spring.threads.virtual.enabled: true spring.datasource.hikari.maximum-pool-size: 50 server.tomcat.max-connections: 45 # 与你之前的并发限制值匹配 server.tomcat.threads.max: 4 # 保持现有配置,仅负责接收连接的平台线程数
当连接数达到45时,后续请求会进入Tomcat的连接队列(默认容量100),超过队列容量的请求会被直接拒绝,确保并发请求数始终在数据库连接池的承载范围内。
方案二:自定义Spring MVC拦截器实现精细化并发控制
如果需要针对特定接口设置不同的并发规则,可通过拦截器结合信号量实现全局或局部的并发限制:
@Configuration class ConcurrentRequestConfig : WebMvcConfigurer { // 设置最大并发数,略低于数据库连接池容量 private val maxConcurrentRequests = 45 private val semaphore = Semaphore(maxConcurrentRequests, true) override fun addInterceptors(registry: InterceptorRegistry) { registry.addInterceptor(object : HandlerInterceptor { override fun preHandle(request: HttpServletRequest, response: HttpServletResponse, handler: Any): Boolean { // 尝试获取并发许可,失败则返回429 if (!semaphore.tryAcquire()) { response.status = HttpStatus.TOO_MANY_REQUESTS.value() response.writer.write("Too many concurrent requests, please try again later.") return false } return true } override fun afterCompletion(request: HttpServletRequest, response: HttpServletResponse, handler: Any, ex: Exception?) { // 无论请求成功与否,都释放并发许可 semaphore.release() } }) // 可选:指定拦截路径,比如只拦截/api/**接口 // .addPathPatterns("/api/**") } }
这种方式的优势是可以根据业务需求灵活调整,比如对高耗资源的接口单独设置更低的并发上限。
关键注意点
- 虚拟线程模式下,
server.tomcat.threads.max的作用仅局限于Tomcat的平台线程池(负责接收TCP连接),无法控制实际处理请求的虚拟线程数量,因此不能再用它限制并发请求。 - 并发数建议设置为略低于数据库连接池最大容量,预留少量连接应对需要多连接的特殊请求,避免连接池耗尽。
内容的提问来源于stack exchange,提问作者Heits
相关产品推荐
相关产品推荐

