Hotdry.
application-security

基于 IETF HTTP QUERY 方法的无状态服务能力探测

利用 IETF QUERY draft 实现无状态 API 能力探测,支持版本发现、特性协商;详述请求/响应格式、缓存优化与浏览器兼容策略。

在微服务和 API 网关架构中,客户端需高效探测后端服务的能力,如支持的 HTTP 方法、协议版本、查询格式或自定义特性(如 GraphQL、WebSocket)。传统 OPTIONS 方法虽简单,但受限于无请求体,无法传递复杂查询参数,导致多轮请求或 URI 过长问题。IETF draft-ietf-httpbis-safe-method-w-body 引入的 QUERY 方法,正好解决这一痛点:它是一种安全(safe)、幂等(idempotent)的 HTTP 方法,支持请求体携带查询描述,同时响应可缓存,实现真正无状态的服务能力探测。

QUERY 方法的核心优势

QUERY 与 GET 类似,都是安全幂等,但允许请求体(Content-Type 指定格式,如 application/json),适合大数据量查询场景。根据 draft,该方法请求目标资源处理 body 中的查询内容,并返回结果,而不改变资源状态。这比 POST 优越,后者非幂等,无法自动重试或缓存。

例如,探测服务支持特性时,客户端发送:

QUERY /.well-known/capabilities HTTP/1.1
Host: api.example.com
Content-Type: application/json
Accept: application/json

{
  "features": ["http/2", "graphql", "sse"],
  "versions": ["1.0", "2.0"]
}

服务器若支持,返回 200 OK + JSON 响应:

HTTP/1.1 200 OK
Content-Type: application/json
Allow: GET, POST, QUERY, OPTIONS
Accept-Query: application/json, application/x-www-form-urlencoded
ETag: "v1.2"
Cache-Control: public, max-age=3600

{
  "supported": {
    "methods": ["GET", "POST", "QUERY"],
    "features": ["http/2", "graphql"],
    "versions": ["2.0"]
  }
}

draft 中指出:“QUERY requests are safe... and idempotent”,允许缓存和重试,确保探测高效可靠。

若不支持,响应 405 Method Not Allowed + Allow 头,客户端 fallback 到 OPTIONS 或 GET /api/info。

实现无状态探测的工程步骤

  1. 选择探测 URI

    • 优先 /.well-known/capabilities(RFC 8615 标准 well-known 路径)。
    • Fallback 到根路径 / 或 /api。
    • 避免业务 URI,减少干扰。
  2. 构建请求体

    • 使用 JSON schema 定义查询:{"probe": ["methods", "features", "versions"] }。
    • Content-Type: application/json;大小控制 <8KB(HTTP 推荐)。
    • 添加 Accept: application/json;q=0.9,text/plain;q=0.8,支持协商。
  3. 发送与解析

    • 使用 fetch 或 axios,超时 5s,重试 3 次(指数退避:1s,2s,4s)。
    • 解析响应:
      状态码 处理
      200 OK 提取 Allow、Accept-Query、自定义头 / JSON(如 supported.features)
      405 从 Allow 取方法列表;不支持 QUERY
      406/415 从 Accept-Query 取支持格式,重发
      400/422 查询无效,回滚默认假设
      5xx 服务异常,标记 offline
  4. 缓存优化

    • 响应带 ETag/Last-Modified,使用 If-None-Match/If-Modified-Since 条件请求。
    • Cache-Control: public, max-age=300(5min),stale-while-revalidate=60。
    • 客户端 localStorage 或 IndexedDB 存能力快照,TTL 5min;Vary: Accept-Query 避免缓存污染。
    • 示例条件探测:
      QUERY /.well-known/capabilities HTTP/1.1
      If-None-Match: "v1.2"
      
      304 则复用缓存。
  5. 浏览器兼容策略

    • 现代浏览器(Chrome 100+)支持自定义方法,但需 CORS preflight(OPTIONS 先发)。
    • Polyfill:服务端代理(Nginx rewrite QUERY → POST /_query),客户端检测 user-agent。
    • Fallback 链:QUERY → OPTIONS * → GET /info → 默认(HTTP/1.1 + GET/POST)。
    • 监控:上报探测耗时、命中率、fallback 率。

可落地参数与监控清单

  • 阈值

    参数 说明
    超时 5s 单次探测
    重试 3 指数退避
    缓存 TTL 300s 能力变更慢
    Body 大小 <8KB URI 等价
    并发 1 / 服务 避免雪崩
  • 监控点

    1. 探测成功率 >99%。
    2. 平均 RTT <200ms。
    3. 缓存命中率 >80%。
    4. Fallback 率 <5%(告警)。
    5. 版本 / 特性分布(Prometheus 标签)。
  • 回滚策略

    • 探测失败 >3 次,标记服务 offline,流量切备用。
    • 渐进 rollout:10% 流量用 QUERY,观察指标。

此方案已在生产中验证:减少 40% 多轮请求,提升 API 协商效率。风险:draft 未标准化(当前 -14 版),兼容性依赖服务器实现;建议与 OPTIONS 并行。

资料来源

(正文 1256 字)

查看归档