如何在Spring DeferredResult场景下感知服务端关闭ReadableStream连接
处理服务端连接关闭的轮询优化方案
1. 给Fetch请求添加超时机制
原生Fetch没有内置超时功能,可通过AbortController手动实现,避免客户端无限等待。修改后的客户端代码如下:
function polling() { console.log("call with fetch"); // 创建AbortController实例用于中断请求 const controller = new AbortController(); const signal = controller.signal; // 设置超时时间(示例为5分钟,可根据业务调整) const timeoutId = setTimeout(() => controller.abort(), 5 * 60 * 1000); fetch('%@[urlPolling]', { signal }) .then(function(response) { clearTimeout(timeoutId); // 请求正常返回,清除超时定时器 console.log(response); // 检查响应状态,服务端连接异常可能返回5xx/4xx状态码 if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return response.text(); }).then(function(data) { console.log(data); var dataJson = JSON.parse(data); if (dataJson.status == "OK" || dataJson.status == "KO") { addLoaderEffect(); console.log("completato"); sendPollingResult(); } else if (dataJson.status == "ERROR") { console.log("error from server, executing polling again"); setTimeout(polling, 3000); } else { // 未知状态触发重试 setTimeout(polling, 3000); } }) .catch((error) => { console.error('Error:', error); // 根据错误类型区分场景 if (error.name === 'AbortError') { console.log("Request timed out, retrying..."); } else { console.log("Connection closed or server error, retrying..."); } setTimeout(polling, 3000); }); } polling();
2. 精准识别连接关闭场景
在catch块中,不同错误类型对应不同的服务端状态:
AbortError:主动触发的超时,说明服务端长时间无响应,大概率已下线TypeError(如"Failed to fetch"):网络连接中断,包含服务端主动关闭连接、实例被替换的情况- HTTP状态码错误(502/503等):服务端实例替换时可能返回这类状态,需在
then阶段通过response.ok提前判断
3. 服务端配合优化
在Spring的DeferredResult逻辑中添加超时和完成回调,主动向客户端返回状态标识:
// Spring端示例代码 DeferredResult<String> deferredResult = new DeferredResult<>(5 * 60 * 1000L); // 设置服务端超时时间 // 超时回调:主动返回超时状态 deferredResult.onTimeout(() -> { deferredResult.setResult(JSON.toJSONString(Map.of("status", "TIMEOUT"))); }); // 连接完成/关闭时的清理回调 deferredResult.onCompletion(() -> { // 可在此处添加资源清理逻辑,若需主动告知客户端连接关闭,也可返回对应状态 }); // 业务逻辑中设置正常结果 // deferredResult.setResult(...);
客户端收到TIMEOUT状态后可直接重试,无需等待。
4. 可选:心跳辅助检测
如果轮询间隔较长,可在轮询间隙添加轻量心跳请求(比如每30秒调用一次服务端健康检查接口),一旦心跳失败,立即触发轮询重试,快速感知服务端状态变化。
内容的提问来源于stack exchange,提问作者AM13
相关产品推荐
相关产品推荐

