接口超时原因分析和实践建议

13,386 阅读3分钟

背景和目标

我经常遇到接口调用超时报异常的问题,以前也会没确定超时原因就去尝试改客户端代码、服务端代码、代理服务器(如nginx)的超时时间设置,有时候能碰巧解决了问题,但有时也会留下了不对症下药的风险。本文目标是为应对超时问题给出系统化建议,会尽量客观分析各类超时原因,但也会存在主观因素和不全面的地方,有不同观点欢迎提出。

超时类型

  1. 客户端超时

    • 通过XMLHttpRequest发送请求

    • 通过axios(调用XMLHttpRequest发送请求)
      • 超时设置:github.com/axios/axios…
      • 客户端现象:当设置超时1000ms时并且未捕获异常时chrome控制台报错如下错误信息timeout of 1000ms exceeded由XMLHttpRequest抛出
  2. 服务端网关或代理(如nginx)超时

  3. 传输链路超时

    • 概念:客户端与服务器通信,除了经过服务器网关(如nginx),还需要经过运营商的路由、网关等设备,其超时设定都会导致接口调用由于传输链路超时而失败

      • 客户端现象: 通过axios调用并且未捕获异常时chrome控制台报错如下

        错误信息Network Error由XMLHttpRequest抛出, 具体原因为ERR_EMPTY_RESPONSE
    • 传输链路超时情况细分
      • nat超时
        • nat概念:NAT(网络地址转换)是为了通过使用少量的公有IP 地址代表较多的私有IP 地址的方式,将有助于减缓可用的IP地址空间的枯竭
        • nat超时解释:关于TCP长连接,NAT超时,心跳包
  4. 服务端超时

    • koa超时设置(由于我比较熟悉koa框架,这里先仅用koa举例说明)

      • 方法1,调用server.setTimeout:github.com/koajs/koa/i…
        • 客户端现象:通过axios调用并且未捕获异常时chrome控制台报错如下错误信息同传输链路超时一样,所以此方法设置超时仅在客户端看不出根本原因,需要服务端配合查日志
      • 方法2,利用koa中间件返回408状态码,可在客户端清晰看到是由于服务端超时导致接口错误

实践建议

  1. 客户端
    • 超时设置:在服务端已经设置超时的情况下依然需要设置客户端超时(XMLHttpRequest和axios默认也不设置),在超时后给用户合理提示。因为当请求未达服务器时会触发传输链路超时,超时时间一般很长,客户端如果不设置超时遇到这种情况会pending很长时间
    • 异常处理:客户端除了处理业务错误、客户端超时错误,还需要捕获由链路超时和服务端超时引起的错误,给用户合理的报错提示
  2. 服务端
    • 超时设置:在性能和稳定性敏感时需要设置,这样可以在必要时关掉长时间没响应的连接,腾出资源去响应新请求。而且,为了在客户端能区分链路超时和服务端超时,服务端需要返回状态码408
  3. 传输链路:传输链路超时不可控,不能绝对避免
  4. 接口设计:综上所述,即使不设置客户端和服务端超时,接口也会超时,因为传输链路会超时。所以如果一个接口耗时很长就需要考虑做异步方案,长达1min以上就必须做异步方案,具体方案有http poll和websocket等,方案选型与细节请参考:docs.microsoft.com/en-us/azure…