下游超时后调用方捕获异常马上重试,没有退避,三秒内线程池活跃数到顶、队列 2000 全满,拒绝次数从 0 跳到 4000。乍看像缓存或者权限的锅,追下去往往不是。

for (int i = 0; i < 3; i++) {
    try { return call(); }
    catch (Exception e) { Thread.sleep(200L << i); }
}

追下去是这么回事:重试没有间隔也没有上限,失败的任务立刻回到池里再排一次,等于把请求量翻倍压回来。池和队列同时被占,正常请求也进不来。

「拒绝后重试打满」相关的验证我通常做两遍,改完一次、隔天再看一次,确认不是临时生效。接口问题先分清是没发出去、发出去了没收到,还是收到了处理失败。

偶发问题先统计频率,一小时几次和一天一次,查法完全不同。

具体做法是,重试加指数退避 首次 200ms 上限 3 秒;限制重试次数 非幂等接口不重试;拒绝时快速失败 让上游降级而不是继续压;观察拒绝次数和队列长度 确认高峰能被削平。

验收就看一点,下游抖动期间拒绝次数控制在百级,队列不再打满,恢复后 1 分钟内回到正常。

作者 9823189