下游一个接口卡住不返回,这边的待处理请求十五分钟涨到一万条,最后报 socket hang up。内存跟着涨了 700MB,所有接口一起超时。日志里能对上时间点,这种反而好排。

http 请求默认不设超时,连接建好之后可以一直等下去。上游不返回也不断开,请求对象和它的上下文都留在内存里,堆积速度等于进来的 QPS。这一点先确认清楚,后面就不用反复试。

const req = http.get({ host, path, timeout: 3000 }, res => res.resume());
req.on('timeout', () => req.destroy(new Error('timeout')));
req.on('error', err => console.error(err.message));

这次卡住的地方就在「http 请求超时」这一环,单独把它拎出来验证,别和其他改动混在同一次发布里。能分两步做的操作就别合成一步,中间看一眼返回值,出问题好判断。

报错里带路径的,先去看那个路径在不在、权限对不对。

处理上按这个顺序:给每个请求设 timeout 连接超时和整体超时分开配;超时后主动 destroy 请求 不要只 reject Promise;接入熔断 连续失败就暂停发往该下游;用 agent 的 maxSockets 限制同时在途的请求数。

结果对不对很好判断,下游卡住时在途请求稳定在 maxSockets 上限 内存不再随等待时间增长。

作者 9823189