超时配置最佳实践

超时配置看似简单,实际上有很多坑。

超时太短会导致正常的请求被误杀,超时太长又失去了保护作用。本节总结超时配置的最佳实践。

超时配置检查清单

# 超时配置检查清单
timeout_checklist:
  - name: "所有 HTTP 客户端都配置了超时"
  - name: "超时值不是默认值(通常是无限的)"
  - name: "超时值基于业务需求而非技术限制"
  - name: "超时有层次:网关 > 服务 > 数据库"
  - name: "超时配置可动态调整"
  - name: "超时失败有监控和告警"

超时值计算方法

方法一:基于历史数据

# 基于 P99 延迟计算超时
def calculate_timeout(historical_p99_ms: float, factor: float = 2.0) -> float:
    """
    超时 = P99 延迟 × 系数

    系数建议:
    - 2.0: 正常场景
    - 2.5: 网络不稳定的场景
    - 3.0: 非常不稳定的场景
    """
    return historical_p99_ms * factor

方法二:基于用户感知

# 基于用户感知的超时配置
user_perception:
  immediate_response: 100    # 用户感觉不到延迟
  fast_response: 1000       # 用户感觉快
  acceptable_delay: 5000    # 用户可以接受
  maximum_patience: 10000   # 用户愿意等待的上限

常见服务的超时配置

timeout-best-practices.yml
# 常见服务的超时配置参考
service_timeouts:
  # 高性能要求的服务
  high_performance:
    - name: "用户登录"
      timeout: 1000      # 1 秒
      reason: "用户等待感"

  # 标准性能要求的服务
  standard:
    - name: "商品查询"
      timeout: 2000      # 2 秒
      reason: "需要数据库查询"

  # 可以慢一点的服务
  flexible:
    - name: "数据统计"
      timeout: 10000     # 10 秒
      reason: "后台任务,用户不需要立即看到"

# 调用链路超时分配
call_chain_allocation:
  total_budget: 5000   # 端到端总共 5 秒

  allocation:
    network_overhead: 500     # 网络开销:500ms
    gateway_processing: 500   # 网关处理:500ms
    service_processing: 2000  # 服务处理:2 秒
    downstream_calls: 2000   # 下游调用:2 秒

超时配置的反模式

反模式一:所有服务用同一个超时

BadTimeout.java
// 错误:所有服务都用 30 秒超时
feign:
  client:
    config:
      default:
        readTimeout: 30000

反模式二:超时太短

TooShortTimeout.java
// 错误:P99 延迟是 2 秒,超时却设置 500ms
connectTimeout: 500
readTimeout: 500

反模式三:没有监控

NoMonitoring.java
// 错误:配置了超时但没有监控
readTimeout: 5000
# 没有告警规则!

本章总结

核心要点

  1. 超时配置要个性化:不同服务、不同场景用不同的超时
  2. 超时要有科学依据:基于历史数据或用户感知
  3. 避免常见反模式:默认值、超时太短、无监控
  4. 超时配置要可调整:运行时可以修改
  5. 超时失败要监控:及时发现超时问题