2. REST与行情接口基础

在动手处理分页、限流与重试之前,必须先建立对接口本身的准确认知。行情接口的很多“坑”,根源并不在分页算法或重试策略,而在于对REST约束、HTTP语义和行情数据特性的理解偏差。本节把这三块基础打牢,后续的实战技巧才有落脚点。

一、REST架构风格:约束而非协议

REST(Representational State Transfer)是一种架构风格,不是标准,也不是协议。它由Roy Fielding在2000年提出,核心思想是:把一切可被操作的对象抽象为“资源”,通过统一的接口对资源进行操作,并让交互保持无状态。判断一个接口是否“够REST”,通常看它是否满足以下约束:

  • 客户端—服务器分离:前端负责展示与交互,服务端负责数据与业务,双方可独立演进。
  • 无状态:每个请求必须携带服务端理解该请求所需的全部信息,服务端不保存会话上下文。这对行情接口尤其重要,因为行情服务通常要横向扩容。
  • 可缓存:响应需明确标识是否可缓存。行情中的静态合约列表、交易日历适合缓存,而实时报价不适合。
  • 统一接口:资源通过URI标识,通过表述(JSON/XML)传输,通过HTTP方法表达操作意图。
  • 分层系统:客户端无需知道是否经过网关、负载均衡或缓存层。

需要强调的是,REST的“无状态”不等于“无连接复用”,也不等于不能有服务端缓存。它约束的是请求语义的完整性:服务端不应依赖上一次请求留下的隐式状态来决定本次响应。

二、HTTP方法与状态码:语义决定行为

行情接口绝大多数是读操作,因此GET占据主导。但理解全部方法的语义,有助于设计合理的接口和正确判断重试边界。

方法 语义 幂等性 行情场景示例
GET 获取资源表述 是 查询某合约的K线、盘口、成交明细
POST 创建资源或触发处理 否 批量订阅、提交回测任务
PUT 全量替换资源 是 更新自选列表配置
DELETE 删除资源 是 取消某条订阅

幂等性是重试策略的关键依据:GET、PUT、DELETE天然可安全重试,POST则需谨慎,通常要配合幂等键。状态码方面,行情接口常见以下几类:

  • 200 OK:正常返回,但要注意“业务错误藏在200里”的情况,需检查响应体中的错误码字段。
  • 400 Bad Request:参数错误,如合约代码不存在、时间区间非法,重试无意义。
  • 401/403:鉴权失败或权限不足,应先刷新而非盲目重试。
  • 404 Not Found:资源不存在,可能是合约已下架。
  • 429 Too Many Requests:触发限流,必须结合Retry-After退避。
  • 500/502/503/504:服务端或网关异常,属于可重试范畴。
判断是否重试,先看方法幂等性,再看状态码类别。4xx通常不重试(429除外),5xx和网络超时才考虑重试。

三、行情数据特点与常见接口形态

行情数据与普通业务数据有显著差异,这些差异直接决定了接口设计和调用方式:

  • 时序性强:数据按时间戳排列,查询几乎总带时间区间。
  • 高频且量大:逐笔成交、盘口快照可能每秒数千条,必须分页或流式获取。
  • 时效敏感:实时报价过期即失效,历史K线则可缓存。
  • 结构相对固定:字段schema稳定,适合批量传输和列式压缩。
  • 存在快照与增量之分:快照接口返回当前全量状态,增量接口返回自某序号后的变化。

常见的行情接口形态可归纳为三类:REST快照/查询接口(如获取最新盘口、历史K线)、REST增量接口(带since/offset参数拉取变更)、WebSocket推送接口(订阅后持续接收)。本课程聚焦REST类接口,其典型请求形态如下:

GET /v1/market/kline?symbol=BTCUSDT&interval=1m&start=1700000000&end=1700003600&limit=500
Authorization: Bearer <>
Accept: application/json

HTTP/1.1 200 OK
Content-Type: application/json
X-RateLimit-Limit: 1200
X-RateLimit-Remaining: 1198

{
  "code": 0,
  "msg": "ok",
  "data": {
    "symbol": "BTCUSDT",
    "interval": "1m",
    "items": [
      {"ts": 1700000000, "o": "42000.1", "h": "42100.5", "l": "41950.0", "c": "42080.3", "v": "12.5"},
      {"ts": 1700000060, "o": "42080.3", "h": "42200.0", "l": "42050.2", "c": "42150.7", "v": "9.8"}
    ],
    "next_cursor": "1700003600"
  }
}

注意响应中的next_cursor和响应头中的X-RateLimit-*,它们分别是分页和限流处理的直接输入。理解这些字段的来源和含义,是后续章节的前提。

四、误区与复盘:别把REST当“用GET取JSON”

实践中常见的误区有几类,值得提前警惕:

  1. 把REST等同于“HTTP+JSON”:忽略了无状态、统一接口和缓存语义,导致接口设计随意,重试和限流策略难以落地。
  2. 用POST做查询:为了绕过URL长度限制或方便传复杂参数而用POST查询,破坏了幂等性,使重试变得危险。
  3. 只看HTTP状态码,不看业务码:很多行情接口在200响应中返回业务错误,若只判断HTTP层,会把失败当成功。
  4. 忽略响应头中的限流信息:等到429才被动退避,而不是根据Remaining主动节流。
  5. 把实时接口当历史接口用:对实时报价做长时间区间查询,既低效又容易触发限流。
行情接口的“成功”必须同时满足:HTTP状态码为2xx、业务码表示成功、返回数据结构符合预期。三者缺一不可,否则重试和分页逻辑都会建立在错误前提上。

下面这张图概括了从一次行情请求发出到判定结果的核心链路,以及各环节对应的关键判断点,可作为后续分页、限流与重试设计的参照。

行情REST请求处理链路与关键判断点 客户端请求 GET + 参数 + 网关/鉴权 限流 · 鉴权 · 路由 行情服务 查询 · 分页 · 组装 响应返回 状态码 · 业务码 · 头 结果判定三要素 ① HTTP 2xx? ② 业务码成功? ③ 数据结构符合预期? 分支处理 429→退避重试 5xx→重试 4xx→修正 分页推进 cursor/offset 更新 直到无更多数据 关键输入:X-RateLimit-Remaining · Retry-After · next_cursor · 业务错误码 这些字段是分页、限流与重试策略的直接依据

把上述基础串起来看:REST约束决定了接口应如何被设计,HTTP方法与状态码决定了请求能否安全重试,行情数据特性决定了分页与限流的必要性。三者共同构成了后续实战章节的判断框架。在真实项目中,建议先对照本节清单检查现有行情接口的语义是否清晰、错误码是否可区分、限流信息是否暴露,再进入分页与重试的具体实现。