长轮询接口 hold 住请求等新消息,网关 30 秒就掐断,客户端收到 504 后马上重连,日志里每分钟出现两次 504,消息还是延迟十几秒才到。乍看像缓存或者权限的锅,追下去往往不是。

curl -s -m 35 'https://api.example.com/v1/poll?since=90210'
# gateway: proxy_read_timeout 30s; app wait 25s

追下去是这么回事:应用的等待时间设成了 50 秒,比网关的读超时还长,连接在网关侧先被断开。客户端把 504 当成失败立刻重连,新请求又要重新建立等待,消息正好落在两次等待的缝隙里。

「长轮询」这个问题文档写得含糊,实际行为以当前版本为准,别照旧版本的结论套。接口问题先分清是没发出去、发出去了没收到,还是收到了处理失败。

具体做法是,应用侧等待时间留出余量 比如网关 30 秒就设成 25 秒;长轮询正常结束返回 200 空结果 不要让它超时;客户端收到 504 先退避一秒再重连 别立刻发起;把等待时长和网关超时写成同一份配置 发版时一起改。

验收就看一点,观察十分钟日志 不再出现 504 新消息从产生到收到控制在两秒内。

作者 9823189