You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot应用高负载下高延迟与线程饥饿问题排查

问题:Spring Boot高负载下线程数未达Tomcat配置上限,引发延迟与线程饥饿

我有一个Spring Boot应用,API端点负责将数据推送至Kafka主题。高负载场景下,应用出现严重延迟,大量请求遭遇线程饥饿,最终因响应超时断开连接。

应用采用CompletableFuture异步推送Kafka数据,正常负载下表现良好,但高负载下无法高效处理,导致性能下降和线程饥饿。

我观察到高负载时仅创建了70-80个线程,尽管Tomcat最大线程数设为300,这种线程限制进一步加剧了延迟和线程饥饿问题。

控制器代码

@RequestMapping(value = "/pushtokafka", method = RequestMethod.POST, consumes = MimeTypeUtils.APPLICATION_JSON_VALUE)
public EventResponse publishEventToKafka(@RequestParam Map<String, Object> map, @RequestBody(required = false) Payload payload) {
    CompletableFuture.runAsync(() -> {
        if (map.containsKey("abc")) {
            eventProducerService.pushtoKafka1(payload);
        } else {
            eventProducerService.pushtoKafka2(payload);
        }
    }, taskExecutor);

    return new EventResponse("success", "Successfully pushed to kafka");
}

自定义线程池配置

@Bean
public Executor taskExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(8); // 核心线程数
    executor.setMaxPoolSize(20); // 最大线程数
    executor.setQueueCapacity(Integer.MAX_VALUE);
    executor.initialize();
    return executor;
}

Tomcat相关配置

server.tomcat.max-threads=300
server.tomcat.connection-timeout=120000
server.tomcat.accept-count=1000
server.tomcat.max-connections=-1
server.tomcat.min-spare-threads=200 

应用版本:Spring Boot 2.2.6.RELEASE,Tomcat 9.0.65

已应用上述配置,但问题仍未解决,想知道高负载下为何没有创建更多线程。


原因分析与优化方向

  • 自定义线程池的阻塞瓶颈
    你的taskExecutor设置了无界队列(Integer.MAX_VALUE),而ThreadPoolTaskExecutor的逻辑是:核心线程满额后,新任务优先进入队列,只有队列满了才会创建新线程直到最大线程数。无界队列导致线程池永远不会扩容到20的最大线程数,异步任务全部积压在队列中。如果Kafka推送是同步阻塞操作,核心线程会长期被占用,无法处理新任务,最终引发整体线程饥饿。

  • Tomcat线程数未达上限的本质
    Tomcat线程处理请求时只是把任务丢给异步线程池就直接返回了,本身占用时间极短,所以即使设置了max-threads=300,也不会触发创建这么多线程。真正的瓶颈在异步线程池的处理能力,而非Tomcat的线程数。

  • 具体优化方案

    1. 调整线程池配置:改为有界队列,触发线程扩容,同时配置合理的拒绝策略避免任务丢失:
      @Bean
      public Executor taskExecutor() {
          ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
          executor.setCorePoolSize(20);
          executor.setMaxPoolSize(50);
          executor.setQueueCapacity(100); // 有界队列
          executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 让Tomcat线程帮忙处理溢出任务
          executor.initialize();
          return executor;
      }
      
    2. 优化Kafka发送逻辑:确保KafkaProducer使用异步发送(带回调),避免同步阻塞占用线程,检查pushtoKafka1/pushtoKafka2的实现是否存在等待响应的逻辑。
    3. 增加线程池监控:通过Micrometer等工具监控队列积压数、线程活跃数、任务拒绝数,精准定位瓶颈。
    4. 调整Tomcat配置:min-spare-threads设为合理值(如50),避免不必要的资源占用,保留max-threads=300应对突发请求量。

内容的提问来源于stack exchange,提问作者alok kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 04:40:23