咨询Azure Web App中Java 8长请求避免闲置超时的实现方法
针对你遇到的Azure App Service长请求超时问题,结合Spring 4和Java 8的技术栈,我整理了几个可行的解决方案,帮你避免请求被判定为闲置而中断:
解决方案1:异步请求+Server-Sent Events(SSE)心跳推送(推荐)
这是最直接的方案——把耗时任务异步化,同时通过SSE定期向客户端发送心跳数据,让Azure知道请求处于活跃状态,不会触发230秒超时。
实现步骤:
- 在Spring控制器中使用异步处理机制,把耗时任务放到后台线程池执行
- 任务执行过程中,每隔30-60秒(必须小于230秒)向客户端推送心跳信息
- 任务完成后,推送最终的响应结果
示例代码:
@RequestMapping(value = "/long-running-task", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public ResponseEntity<StreamingResponseBody> executeLongTask() { // 启动后台耗时任务 CompletableFuture<String> taskFuture = CompletableFuture.supplyAsync(() -> { try { // 模拟5分钟的耗时操作 for (int progress = 0; progress <= 100; progress += 10) { Thread.sleep(30000); // 每30秒推进10%进度 // 这里可以记录进度到缓存或内存,用于心跳推送 } return "任务执行完成,最终结果..."; } catch (InterruptedException e) { Thread.currentThread().interrupt(); return "任务被中断"; } }); // 构建流式响应,定期发送心跳 StreamingResponseBody responseBody = outputStream -> { PrintWriter writer = new PrintWriter(outputStream); // 定时发送心跳 ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); scheduler.scheduleAtFixedRate(() -> { if (!taskFuture.isDone()) { writer.write("data: 任务进行中,当前进度xxx%\n\n"); writer.flush(); } }, 0, 30, TimeUnit.SECONDS); // 等待任务完成,发送最终结果 String finalResult = taskFuture.get(); scheduler.shutdown(); writer.write("data: " + finalResult + "\n\n"); writer.flush(); }; return ResponseEntity.ok() .contentType(MediaType.TEXT_EVENT_STREAM) .body(responseBody); }
前端可以用EventSource对象接收SSE消息,处理心跳和最终结果,兼容性也不错。
解决方案2:拆分长任务为「提交+轮询」模式
如果SSE不适合你的业务场景,可以把长任务拆成两步,彻底避免长连接:
- 第一步:客户端发送请求提交任务,服务器立即返回一个唯一的
taskId,同时在后台启动耗时任务 - 第二步:客户端每隔30秒用
taskId轮询服务器,查询任务进度或结果 - 服务器把任务进度/结果存储在内存缓存或Redis中,轮询时返回对应状态
这种方式完全规避了Azure的长连接超时限制,而且对前端技术栈没有特殊要求,兼容性拉满。
解决方案3:优化应用线程配置(辅助措施)
虽然Azure的230秒超时无法修改,但可以确保应用的后台线程配置合理,避免因为线程耗尽导致任务排队变慢:
- 在Spring中配置合适的
TaskExecutor,确保后台任务有足够的线程资源 - 检查Azure App Service的实例规格,确保CPU和内存能支撑耗时任务的执行,避免资源不足拖慢任务
关键注意事项
- 绝对不要在Tomcat的请求线程中直接执行耗时任务,必须异步化,否则不仅会触发Azure超时,还会耗尽工作线程导致应用无法处理其他请求
- 心跳间隔一定要小于230秒,建议30-60秒,确保Azure始终能收到响应数据
- 对于JSP页面的长请求,建议把业务逻辑移到后台任务,JSP只负责发起任务和展示进度,不要在JSP中阻塞等待任务完成
内容的提问来源于stack exchange,提问作者Foramkumar Parekh
相关产品推荐
相关产品推荐

