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

Spring中Controller执行无限循环后未返回响应的排查求助

问题分析与解决思路

代码逻辑说明

接口整体流程为:Controller接收请求后,调用业务处理方法,其中包含一个最长耗时数小时的阻塞循环(当前场景耗时15分钟),循环结束后回到Controller打印日志,再返回响应。但部分请求出现日志已打印、但响应无法返回的情况,客户端(Postman)一直显示"Sending request..."。

Controller.java 接口代码

@GetMapping("/endpoint")
public ResponseEntity<?> addDocument(@RequestParam String param1, @RequestParam String param2) {

    AddDocumentRequest request = new AddDocumentRequest(param1, param2);

    callRequestHandler(request);

    log.info("Job Done");
    return ResponseEntity.ok(true);
}

Controller.java 中 callRequestHandler 方法

private void callRequestHandler(AddDocumentRequest request) {
    try {
        requestHandler.requestHandler(request);
    } catch (Exception e) {
        log.error("error");
    }
}

RequestHandler.java(@Service类)中 requestHandler 方法

public void requestHandler(AddDocumentRequest request) throws Exception {

    // 调用@Async方法
    CompletableFuture<String> registry = service.addDocuments(request);

    // 阻塞线程等待目标状态
    blockAndWaitResponses(request);
}

阻塞循环方法 blockAndWaitResponses

private void blockAndWaitResponses(AddDocumentRequest request) throws Exception {
    while (true) {
        // 忙等待
        Thread.sleep(120000); // 2分钟

        if (desiredStateOccured()) {
            insertDataToDB();
            break;
        } else {
            updateState();
        }
    }
}

可能的原因排查方向

  • Tomcat工作线程池耗尽:长时间阻塞的请求会占用Tomcat工作线程,当并发请求超过maxThreads配置时,后续请求会进入等待队列。若队列满(acceptCount),新请求会被拒绝;即使日志已打印,也需确认线程是否真的释放,可通过JVM线程栈(jstack)查看当前工作线程状态。
  • 响应发送阶段阻塞:Spring MVC在返回响应时,可能被自定义过滤器/拦截器、或Tomcat的响应缓冲区配置卡住。比如某些Filter在afterCompletion阶段执行耗时操作,或缓冲区未及时刷新。
  • 隐性资源未释放:insertDataToDB()虽未抛出异常,但可能存在数据库连接未释放、事务未提交等情况,间接导致线程无法正常完成响应流程。可在该方法末尾添加日志,确认执行完成时间点。
  • 网络/客户端超时:Postman或中间代理(如网关、Nginx)的超时设置可能导致客户端提前断开连接,但服务端仍在处理。可换用curl等工具测试,对比结果。
  • Spring请求上下文异常:长时间阻塞后,请求上下文(如RequestContextHolder)可能被意外清理,导致Spring无法正确组装响应。

解决建议

  • 监控线程状态:出现问题时,用jstack <pid>导出线程栈,查看执行完log.info("Job Done")的线程是否卡在org.apache.catalina.connector.CoyoteAdapter.service等响应发送相关方法上。
  • 排查过滤器/拦截器:暂时禁用自定义Filter/Interceptor,测试是否能正常返回响应,逐步定位问题点。
  • 添加响应阶段日志:通过Spring的HandlerInterceptor在postHandle和afterCompletion阶段添加日志,确认响应处理的各个时间节点。
  • 调整Tomcat配置:适当增大maxThreads缓解线程池压力,同时设置connection-timeout和keep-alive-timeout,避免无效连接占用资源。
  • 验证数据库操作:在insertDataToDB()中添加详细日志,确认事务提交、连接释放的时间,排除隐性阻塞。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 11:02:07