fix(实例路由): 转发失败不再伪装成「任务不存活」
归属节点滚动重启时跨节点转发会连接失败,原来返回 ApiResponse.fail(40903) —— HTTP 200 + data:null。客户端把「拿不到数据」解析成 alive=false,于是把健康的长 任务主动停掉(2026-09-18 任务 28616:跑到 66/253 被自杀,只跑到第 2/6 页)。 改为 503 + 空 body:新客户端按状态码判未知继续跑;老客户端因 body 不是 JSON、 resp.json() 抛异常也落到未知——两边都不会再把未知当成死。顺带让这类故障在 HTTP 指标里可见(原先记成 200,滚动重启期间丢了多少心跳监控完全看不到)。
This commit is contained in:
+10
-1
@@ -55,10 +55,19 @@ public class GlobalExceptionHandler {
|
||||
? ApiResponse.fail(forwardEx.getMessage())
|
||||
: ApiResponse.fail(forwardEx.getCode(), forwardEx.getMessage());
|
||||
} catch (Exception forwardEx) {
|
||||
// 转发失败是**瞬时基础设施故障**(归属实例正在滚动重启),不是业务结论,
|
||||
// 更不能表达成「任务不存活」。原先返回 ApiResponse.fail(40903) —— HTTP 200
|
||||
// 加 data:null,而客户端那句 bool((resp.json().get("data") or {}).get("alive"))
|
||||
// 会把「拿不到数据」折叠成 alive=false,于是客户端把**健康的长任务主动停掉**:
|
||||
// 2026-09-18 任务 28616 就是这么死的(归属节点 server-110 重启窗口内,心跳经
|
||||
// nginx 落到 server-121,转发 3 次 Connection refused 后返回空 data)。
|
||||
// 改为 503 + 空 body:新客户端按状态码判为「未知」继续跑;老客户端因 body 不是
|
||||
// JSON、resp.json() 抛异常,同样落到「未知」。顺带让这类故障在 HTTP 指标里可见
|
||||
// (原先记成 200,监控完全看不到滚动重启期间丢了多少心跳)。
|
||||
log.warn("[instance-routing] forward failed taskId={} operation={} owner={} current={} msg={}",
|
||||
ex.getTaskId(), ex.getOperation(), ex.getOwnerInstanceId(), ex.getCurrentInstanceId(),
|
||||
forwardEx.getMessage(), forwardEx);
|
||||
return ApiResponse.fail(40903, "任务归属实例转发失败: " + forwardEx.getMessage());
|
||||
return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).build();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user