交易技术

交易API接口选择:REST与WebSocket的性能博弈

在实时数据推送测试中,WebSocket相较于REST API的传输效率提升最高可达98.5%。这个数字足够醒目,但不能直接转化为交易系统结论。…

交易API接口选择:REST与WebSocket的性能博弈

原因很简单。REST与WebSocket解决的不是同一个问题。

REST是基于HTTP的无状态请求—响应模型。适合查询、配置、权限和状态恢复。WebSocket在单个TCP连接上提供持久化的全双工通信。适合行情推送、Tick流和订单状态通知。两者的性能差异,首先来自通信模型。其次来自接口所在的系统平面。最后来自断线、重连、补数和幂等处理。

因此,交易API接口选择不能简化为“WebSocket更快,REST更慢”。正确的问题是:哪个接口应当承担哪类数据,哪一段延迟属于真正的交易路径,断线后系统是否还能恢复一致状态。

先拆开交易系统:三个平面不是一个接口

交易系统通常可以拆分为三个平面:

1. 执行平面:负责下单、撤单、改单、成交回报和订单状态变更。

2. 流平面:负责行情、Tick、盘口、逐笔成交和实时事件推送。

3. 控制平面:负责账户查询、持仓查询、资金查询、权限核验、参数配置和历史数据读取。

这三个平面的访问模式不同。把它们全部塞进同一种接口,通常意味着架构边界没有被定义清楚。

执行平面关心的是状态转换。

订单从未提交,进入已提交;从已提交进入部分成交、完全成交、撤单或拒单。每个状态都必须可追踪。接口是否低延迟只是一个指标,不能覆盖状态丢失、重复执行和回报乱序。

流平面关心的是连续传输。

行情不是一次请求的结果,而是持续到达的事件集合。客户端需要处理连接存活、消息顺序、序列号、断线重连、重复消息和历史补全。这里的核心指标不是单次请求响应,而是消息到达延迟、吞吐、抖动和丢失后的恢复能力。

控制平面关心的是确定性。

账户配置、权限校验、历史数据查询通常不需要每毫秒更新一次。接口要具备清晰的请求参数、明确的返回结构、稳定的错误码和可重复执行能力。REST的无状态模型在这里更合适。

交易接口的第一层优化不是换协议,而是把执行、流和控制从同一条路径中拆开。

三个平面的接口倾向

系统平面典型操作更适合的接口主要原因
执行平面下单、撤单、改单、查询订单REST或专用交易接口,配合WebSocket回报请求需要明确确认,回报需要持续推送
流平面行情、Tick、盘口、成交推送WebSocket长连接、双向通信、减少重复握手
控制平面账户、持仓、权限、历史数据REST无状态、易缓存、易负载均衡、便于审计
恢复平面断线补数、订单重查、状态校正REST为主通过请求获得完整快照,恢复本地状态

这里的“更适合”不是协议限制。技术上可以使用REST轮询行情,也可以通过WebSocket传输账户信息。问题是成本和故障边界。

用REST轮询实时行情,系统必须不断发起请求。行情没有变化时,请求仍然存在。行情变化较快时,轮询间隔决定数据延迟。间隔过短,产生大量无效请求;间隔过长,数据滞后。

用WebSocket承载账户查询,客户端则需要维护连接、订阅关系、消息路由和异常恢复。对于偶发查询,这套状态管理的复杂度通常没有收益。

接口设计应先匹配数据流,再讨论延迟。

REST的优势:简单、无状态、可恢复

REST架构风格由Roy Thomas Fielding于2000年提出。其核心特征之一是无状态请求—响应。服务器不依赖此前请求保存客户端会话上下文。每次请求都携带完成处理所需的信息。

在交易系统中,这个特征有三个直接价值。

请求边界清晰

一次查询对应一次请求。请求参数、身份信息、资源路径和返回结果可以被独立记录。

例如查询账户资金,服务端收到请求后返回当前快照。查询完成后,请求生命周期结束。客户端不需要维持一条持续存在的通信链路,也不需要判断某条消息是否属于上一次查询。

这对日志、审计和故障定位有利。

当接口返回错误时,可以定位到具体请求。参数、时间、账户标识、权限上下文和响应码都能被记录。对于控制平面,这是比极限低延迟更重要的性质。

天然适合负载均衡

REST使用标准HTTP动词访问资源。常见方法包括:

  • GET用于读取资源,例如历史K线、账户信息和订单列表。
  • POST用于创建操作,例如提交订单或发起特定业务请求。
  • PUT用于整体更新资源。
  • DELETE用于撤销或删除资源。

由于请求之间相互独立,网关可以根据请求进行负载均衡。服务节点不必保存持续连接状态。缓存、限流、认证和访问控制也可以在HTTP层完成。

这并不意味着REST没有服务端状态。订单本身当然有状态。这里的无状态,是指协议请求不依赖某个连接上的隐含上下文。订单状态存储在交易系统或数据库中,而不是依赖客户端是否保持某条HTTP连接。

适合状态快照和数据补全

WebSocket适合事件流。事件流天然存在一个问题:客户端可能在某个时间点断开。

断开期间发生的订单更新,不会自动出现在本地。恢复连接后,客户端不能只等待下一条推送。它需要重新获取当前快照,或者根据序列号补齐缺失区间。

REST在这里承担恢复接口。

典型流程是:

1. WebSocket连接断开。

2. 客户端记录最后一个已处理的消息序列号。

3. 客户端重新建立WebSocket连接。

4. 通过REST查询订单、持仓、资金和必要的历史事件。

5. 对比本地状态与服务端快照。

6. 修正差异。

7. 恢复实时订阅。

这个流程的核心不是快,而是可验证。只要服务端能够返回确定的状态快照,客户端就有机会将本地状态重新收敛到服务端状态。

REST的瓶颈来自HTTP开销

REST的问题也很明确。每次请求都需要携带HTTP请求信息。即使使用连接复用,方法、路径、认证、内容类型和其他请求头仍会产生额外数据。

相关测试资料显示,REST每个请求可能附带数百字节的HTTP头部;WebSocket完成握手后,数据帧头通常只有2至10字节。具体开销取决于实现、掩码、负载长度、压缩方式和网络栈配置,但数量级差异客观存在。

对于账户查询,这种开销通常可接受。

对于每秒大量变化的盘口数据,情况不同。若客户端通过REST不断拉取行情,即使接口响应体很小,也要反复支付请求调度、头部传输、服务端路由和序列化成本。

此时瓶颈不一定是带宽。可能是:

  • HTTP请求数量过多。
  • 网关和认证层重复执行。
  • 客户端线程频繁唤醒。
  • JSON序列化和反序列化占用处理时间。
  • 轮询周期导致数据延迟。
  • 多个策略重复请求相同数据。
  • 负载均衡层积累无效请求。

所以,REST不适合作为高频实时行情的主要传输方式。不是因为HTTP必然慢,而是因为请求—响应模型与持续事件流不匹配。

WebSocket的优势:连接一次,持续传输

WebSocket协议在2011年完成标准化。它允许客户端与服务端在单个TCP连接上建立持久化的双向通信。

连接建立后,服务端可以主动发送消息。客户端也可以主动发送订阅、取消订阅、心跳和控制指令。双方不需要为每条消息重新建立完整的HTTP请求流程。

这改变了数据传输的基本单位。

REST的基本单位是请求。WebSocket的基本单位是消息或数据帧。

实时行情更适合事件推送

行情数据具有明显的事件特征。

价格变化、盘口变化、成交发生、订单状态更新,都可以直接转化为消息。服务端在事件产生后推送数据。客户端不再通过时间间隔猜测数据是否变化。

这个差异直接影响延迟。

REST轮询的最小延迟受轮询周期约束。如果每100毫秒发起一次请求,理论上客户端可能在事件发生后立即拿到结果,也可能等待接近100毫秒。实际还要叠加网络、排队和处理时间。

WebSocket不需要等待下一次轮询。消息生成后可以直接写入连接。延迟主要来自事件生成、队列排队、序列化、网络传输和客户端处理。

它降低的是通信层等待,不是整个交易系统的全部延迟。

全双工并不等于低延迟保证

WebSocket提供全双工通信,但协议能力不等于系统性能。

如果服务端消息队列持续堆积,客户端线程被阻塞,或者JSON解析成为热点,长连接也不会自动变快。若网络发生抖动,TCP重传仍会影响消息到达。若客户端只建立一条连接承载所有市场和账户事件,任何一个处理瓶颈都会扩大影响范围。

需要观察完整链路:

1. 数据源何时生成事件。

2. 服务端何时接收事件。

3. 服务端何时完成编码。

4. 消息何时进入发送队列。

5. TCP数据何时离开内核缓冲区。

6. 客户端何时收到数据。

7. 客户端何时完成解析。

8. 策略线程何时读取数据。

9. 下单请求何时进入执行模块。

只测客户端收到消息的时间,不足以判断系统延迟。

WebSocket减少了重复网络开销

完成握手后,WebSocket使用数据帧传输。相关资料给出的典型帧头开销为2至10字节。与每次请求可能附带数百字节HTTP头部相比,持续传输更节省网络空间。

这对高频行情尤其重要。

盘口数据经常包含多个价位、价格数量、更新类型和时间戳。如果每次更新都通过独立HTTP请求传递,协议头部可能比有效负载更大。WebSocket将连接建立成本摊薄到大量消息上。

在实时推送测试中,WebSocket相较于REST的响应性能提升最高可达98.5%。这个结果可以说明传输模型存在显著差异,但不能直接迁移到所有交易所、所有网络环境和所有语言运行时。

测试结果必须标明至少四个条件:

  • 数据源类型。
  • 消息频率。
  • 消息大小。
  • 测量起止点。

缺少这些条件,百分比没有足够解释力。

真正的性能指标不是“快不快”

“REST与WebSocket谁更快”是一个过于粗糙的问题。交易系统需要拆分指标。

延迟

延迟至少包括以下几类:

  • 连接建立延迟:从发起连接到完成可用状态。
  • 首条消息延迟:订阅后收到第一条有效消息的时间。
  • 单条消息传输延迟:服务端发送到客户端接收。
  • 解析延迟:从收到字节到形成结构化对象。
  • 排队延迟:消息进入队列到被线程处理。
  • 策略触发延迟:行情更新到策略逻辑开始执行。
  • 下单链路延迟:策略决定到请求进入交易柜台。
  • 回报延迟:订单提交到收到执行结果。

WebSocket主要改善连接复用和消息推送路径。它不能替代低延迟网络、内核调优、内存管理和柜台接口优化。

抖动

平均延迟没有足够价值。

一个接口平均延迟很低,但偶尔出现长尾阻塞,仍然可能破坏策略执行。应观察中位数、分位数和最大值。实际测试中,至少需要记录P50、P95、P99,并区分正常时段、消息洪峰和重连阶段。

如果只报告平均值,长尾会被隐藏。

吞吐

行情接口需要测量单位时间内可处理的消息数量。订单接口则更关心单位时间内可接受的请求数、排队深度和拒绝率。

吞吐不能脱离消息大小讨论。每秒1000条小消息与每秒1000条深度盘口消息,对网络和解析器的压力不同。

完整性

高频行情可以容忍部分中间更新被合并,但订单状态通常不能缺失。

因此要区分:

  • 是否允许丢失中间行情。
  • 是否必须保证订单回报不丢。
  • 是否存在消息序列号。
  • 是否能够按序处理。
  • 是否支持历史补发。
  • 是否可以用快照校正。
  • 重复消息是否可以安全处理。

协议本身不会替你完成这些工作。

资源占用

需要同时观察:

  • 客户端CPU。
  • 服务端CPU。
  • 内存分配次数。
  • 网络带宽。
  • 线程数量。
  • 连接数量。
  • 队列长度。
  • 垃圾回收暂停。
  • 日志写入量。

在高频系统中,JSON解析可能比网络传输更慢。字符串转数字、对象创建和动态字典访问都可能成为热点。换协议前,先用性能分析器定位瓶颈。

长连接降低了通信开销,但不会自动消除队列、解析器和垃圾回收造成的延迟。

重连机制:WebSocket最容易被低估的成本

WebSocket的持续连接是优势,也是故障边界。

连接一旦断开,实时推送就会停止。客户端需要重新认证、重新订阅,并判断断线期间发生了什么。对行情来说,问题是数据缺口。对订单来说,问题是状态不确定。

针对加密货币数据流的测试显示,WebSocket断开后重新建立连接通常需要0.66秒至1.93秒,首条消息接收延迟低于0.2秒。这个范围只能作为相关场景的参考,不能当作所有交易平台的固定参数。

在重连期间,可能出现三种状态:

1. 客户端已经断开,但服务端仍然认为连接存在。

2. 客户端重新连接成功,但订阅尚未恢复。

3. 客户端已经收到新消息,但断线期间的历史消息缺失。

第三种情况最危险。连接看起来正常,数据实际上不完整。

重连不能只写一个循环

很多客户端的重连逻辑类似于:

1. 连接失败。

2. 等待几秒。

3. 再次连接。

4. 连接成功后继续运行。

这不够。

可靠的重连模块至少要处理以下状态:

  • 连接建立中。
  • 认证中。
  • 订阅提交中。
  • 正常接收中。
  • 心跳超时。
  • 主动关闭。
  • 被服务端关闭。
  • 等待重连。
  • 快照恢复中。
  • 增量消息追赶中。
  • 重新进入正常状态。

每个状态都需要有明确的进入条件和退出条件。否则,系统会出现重复订阅、重复消费或状态假成功。

需要区分连接恢复和数据恢复

连接恢复只说明TCP链路重新建立。它不说明业务数据已经完整。

数据恢复通常需要:

  • 记录最后处理的序列号。
  • 请求当前账户和订单快照。
  • 获取断线区间的增量事件。
  • 检查消息顺序。
  • 丢弃重复消息。
  • 对无法补齐的区间进行重新初始化。
  • 记录恢复结果。

如果服务端支持按序列号补发,优先使用增量补偿。如果不支持,则使用REST快照进行校正。

对订单状态而言,快照查询不能简单覆盖本地状态。客户端还需要考虑快照生成时间和实时事件到达时间。否则会出现先收到新事件,再读到旧快照,导致本地状态回退。

一种常见处理方式是:

1. 记录开始恢复时的实时序列号。

2. 获取账户和订单快照。

3. 暂存恢复期间到达的实时消息。

4. 应用快照。

5. 按序处理暂存消息。

6. 检查序列号是否连续。

7. 继续正常消费。

如果没有序列号,至少需要使用服务端时间、订单更新时间和状态版本进行交叉校验。缺少版本信息时,恢复逻辑只能依赖重复查询,可靠性下降。

执行平面:WebSocket下单并不天然更优

很多交易API同时提供REST下单和WebSocket下单。此时不能只看连接方式。

下单延迟由多个部分组成:

  • 客户端生成请求。
  • 请求排队。
  • 序列化。
  • 网络传输。
  • 网关认证。
  • 风控检查。
  • 交易服务排队。
  • 柜台处理。
  • 交易所或撮合系统接收。
  • 执行结果返回。

WebSocket减少了请求层的连接和头部开销,但不代表服务端的风控、排队和柜台处理时间消失。

在极端低延迟的超高频交易中,FIX协议、专用原生TCP接口或柜台API通常比标准WebSocket更常见。国内股票和期货柜台也经常使用私有TCP、UDP或专用接口。REST与WebSocket的比较,不能替代对具体柜台协议的分析。

下单接口必须具备幂等设计

WebSocket断开时,最危险的动作不是重连,而是重复下单。

客户端发送下单请求后,如果连接在响应返回前断开,客户端无法直接知道服务端是否已经接受订单。此时重新发送相同订单可能造成重复执行。

解决方法不是“再发一次”。需要设计客户端订单标识和幂等查询。

基本流程如下:

1. 客户端为每次业务下单生成唯一请求标识。

2. 发送请求并记录本地日志。

3. 等待确认或订单回报。

4. 连接断开后,不立即重复下单。

5. 通过REST或查询接口检索该请求标识对应的订单。

6. 确认服务端不存在该请求后,才决定是否重试。

7. 将重试次数和结果写入审计日志。

如果交易柜台不支持幂等键,则只能通过客户端订单号、时间窗口、合约、价格、数量和方向进行组合查询。这个方法不如原生幂等键可靠。

订单回报和下单请求可以使用不同通道

一种实用的混合方式是:

  • 使用REST提交低频控制类订单。
  • 使用WebSocket接收订单状态和成交回报。
  • 使用REST查询订单快照。
  • 使用专用柜台API承担对延迟敏感的执行路径。

这样做的好处是职责清晰。

下单请求具有明确的开始和结束。订单回报具有持续事件属性。查询接口承担补偿和核对。每一类通信都使用更匹配的模型。

数据编码和客户端实现决定了另一半性能

协议层只是第一层。客户端实现可能完全改变结果。

JSON不是免费格式

REST和WebSocket都经常使用JSON。WebSocket减少了帧和连接开销,但如果每条消息都需要创建大量临时对象,CPU消耗仍然很高。

高频行情中常见的解析成本包括:

  • 字符串切分。
  • 数字字符串转换。
  • 字段名哈希。
  • 动态对象分配。
  • 嵌套结构遍历。
  • 时间戳解析。
  • 小数精度转换。
  • 垃圾回收。

如果数据源允许,优先使用字段固定、结构简单的消息格式。对于高吞吐场景,可以评估二进制协议、预分配缓冲区和零拷贝解析。但这需要服务端、客户端和测试工具同时支持。

仅仅把REST改成WebSocket,再保留低效的对象模型,收益可能低于预期。

连接数量不能无限增加

为不同订阅建立独立连接,可以隔离故障。连接过多也会增加:

  • 文件描述符。
  • 内核缓冲区。
  • 心跳流量。
  • TLS维护成本。
  • 线程或事件循环负担。
  • 重连风暴风险。

连接数量应根据消息类型、服务端限制和故障隔离要求决定。

常见划分包括:

  • 行情连接。
  • 订单回报连接。
  • 账户事件连接。
  • 管理控制连接。

但不应为了形式上的模块化而创建大量连接。更合理的做法是先测量单连接吞吐、消息队列长度和处理延迟,再决定拆分边界。

心跳与超时参数需要数据支撑

心跳间隔太长,无法及时发现断线。间隔太短,增加网络和服务端负担。

客户端应区分:

  • TCP连接仍然存在。
  • WebSocket协议仍然有响应。
  • 业务消息仍然在正常到达。

前两者正常,不代表第三者正常。行情长时间没有变化时,业务消息可能自然为空。因此需要协议心跳和业务层监控同时存在。

超时不能直接使用一个全局数值。连接超时、认证超时、订阅确认超时、业务回报超时分别对应不同故障。

REST与WebSocket的混合架构

对于量化交易系统,最稳妥的方案通常不是二选一,而是按平面组合。

推荐的职责分配

功能首选接口备用或配套接口设计重点
实时行情WebSocketREST历史数据订阅、序列号、断线补数
Tick推送WebSocketREST时间段查询防止重复和漏报
订单回报WebSocketREST订单查询以服务端状态为准
下单REST、WebSocket或专用柜台查询接口幂等、确认、重试
撤单REST、WebSocket或专用柜台订单状态查询防止连接异常导致重复操作
账户余额RESTWebSocket账户事件定期快照校正
持仓查询RESTWebSocket状态推送处理断线后的状态恢复
历史行情REST本地数据库分页、缓存、限流
权限与配置REST无需长连接审计、缓存和版本控制

这里的下单接口没有固定答案。不同平台的接口实现差异很大。需要以交易柜台文档、实际限流规则和端到端测量为依据。

控制面与数据面分离

量化系统不应让控制请求和行情消息争用同一条处理链路。

控制面包括:

  • 登录。
  • 获取令牌。
  • 读取配置。
  • 查询账户。
  • 查询历史数据。
  • 管理订阅。

数据面包括:

  • Tick。
  • 深度行情。
  • 成交回报。
  • 订单状态事件。

如果控制面请求阻塞了数据面处理,行情消息会在队列中堆积。反过来,行情洪峰也可能拖慢账户查询。

应在进程、线程、事件循环或服务层面建立隔离。隔离粒度取决于系统规模。小型策略可以通过独立任务和有界队列实现。大型系统则需要独立行情服务、订单服务和状态服务。

REST用于恢复,不是仅用于备用

很多架构把REST定义为WebSocket故障后的备用通道。这种定义不完整。

REST还可以主动承担:

  • 启动时获取初始快照。
  • 定时校验本地状态。
  • 断线后补充缺失数据。
  • 重新确认订单终态。
  • 检查账户资金和持仓。
  • 为回测与实盘提供统一查询接口。

WebSocket负责事件,REST负责事实快照。事件与快照组合后,系统才具备状态恢复能力。

测试方法:不要只测一次请求

接口选型必须建立测试矩阵。至少覆盖以下场景:

1. 空载延迟:没有消息洪峰时测量基本延迟。

2. 稳定流量:以接近真实的Tick频率持续运行。

3. 突发流量:模拟开盘、数据集中变化和消息洪峰。

4. 连接抖动:主动断开、网络延迟、丢包和短时不可用。

5. 服务端限流:观察达到请求上限后的响应。

6. 客户端阻塞:模拟策略线程处理变慢。

7. 重连恢复:测量从断线到数据完整的时间。

8. 重复消息:验证幂等与去重。

9. 乱序消息:验证序列号和版本处理。

10. 长时间运行:检查内存增长、连接泄漏和队列积压。

测量点要固定

建议在以下位置打时间戳:

  • 数据源生成时间。
  • 服务端接收时间。
  • 服务端发送时间。
  • 客户端内核接收时间。
  • 客户端解析完成时间。
  • 策略读取时间。
  • 请求发送时间。
  • 服务端确认时间。
  • 订单回报时间。

时间戳需要统一时钟。跨机器测量时,要处理时钟同步误差。否则,得到的不是延迟,而是多个时钟偏移量的混合结果。

记录分布,不记录单值

单次测试结果无法说明系统特征。

应当记录完整样本,然后计算:

  • 最小值。
  • 中位数。
  • P95。
  • P99。
  • 最大值。
  • 超时数量。
  • 重连数量。
  • 丢失消息数量。
  • 重复消息数量。
  • 队列峰值。
  • CPU和内存峰值。

对于WebSocket,需要单独记录重连阶段的指标。正常连接时低延迟,不代表断线后恢复可靠。

对于REST,需要单独记录请求失败、服务端限流和网关排队。平均响应快,但在突发流量中大量返回限流错误,同样不能用于执行平面。

数据库与本地缓存:接口性能的下游约束

接口拿到数据后,还要进入本地缓存、策略内存和数据库。下游处理慢,接口层的优化会被抵消。

行情数据通常不适合逐条同步写入关系型数据库。逐条写入会产生大量事务和索引操作。更合理的方式是:

  • 实时链路只保留策略需要的最新状态。
  • 历史数据通过批量写入。
  • 行情事件进入有界队列。
  • 数据落库与策略处理解耦。
  • 按时间、合约或品种进行分区。
  • 对不需要查询的原始字段减少存储。

订单和成交数据则需要更强的持久化要求。至少要保证请求标识、服务端订单号、状态版本、更新时间和原始回报可追溯。

数据库不是接口的附属组件。状态恢复依赖它保存的本地事实。如果客户端只保留最终状态,不保留事件和版本,断线后很难判断状态变化过程。

交易柜台API:不要用Web协议替代专用接口

REST与WebSocket适合开放平台、云端交易接口和部分交易所数据服务。它们不等同于柜台协议。

在股票、期货和部分专业交易系统中,柜台API可能使用专用TCP、UDP、FIX或厂商私有协议。其认证、报单、回报和风控链路都由柜台定义。即使柜台同时提供REST或WebSocket封装,封装层也可能增加网关、序列化和转发开销。

交易柜台API性能优化通常需要关注:

  • 客户端与柜台的网络距离。
  • 连接是否专用。
  • 是否存在中间代理。
  • 报单线程是否被日志阻塞。
  • 请求是否经过重复序列化。
  • 回报是否与行情共用线程。
  • 柜台是否有明确的序列号。
  • 会话断线后如何恢复。
  • 撤单和重报是否具备幂等机制。
  • 限频规则是否按账户、连接或接口维度计算。

这些问题不能通过更换REST或WebSocket名称解决。

参数优化:先稳定,再降低延迟

对于交易系统接口,参数优化应当有顺序。

第一阶段:确认数据正确

检查:

  • 消息是否完整。
  • 序列号是否连续。
  • 订单状态是否可恢复。
  • 重复消息是否能安全处理。
  • 快照与增量是否能合并。
  • 时间戳是否统一。
  • 本地状态是否会回退。

数据错误时,延迟优化没有意义。

第二阶段:确认故障可控

检查:

  • 心跳超时是否有效。
  • 重连是否会形成连接风暴。
  • 订阅是否重复。
  • 断线期间是否有明确标记。
  • 未确认订单是否会被重复提交。
  • 服务端限流后是否采用退避。
  • 队列满时是否有丢弃策略。

不能处理故障的低延迟系统,只是更快地进入错误状态。

第三阶段:定位实际热点

使用运行时性能分析工具观察:

  • 网络读写。
  • JSON解析。
  • 内存分配。
  • 锁竞争。
  • 队列等待。
  • 日志写入。
  • 数据库提交。
  • 垃圾回收。
  • 上下文切换。

如果主要耗时在JSON解析,换成WebSocket可能只得到有限收益。如果主要耗时在HTTP网关排队,连接复用和接口拆分可能有效。如果主要耗时在柜台排队,客户端优化不会改变端到端延迟。

第四阶段:再调整连接和编码

可调整的参数包括:

  • 连接数量。
  • 心跳间隔。
  • 读写超时。
  • 消息批量大小。
  • 压缩策略。
  • 队列容量。
  • 批量落库间隔。
  • 订阅拆分方式。
  • 重连退避时间。
  • 快照校验周期。

每次只改变一个主要变量。否则无法判断收益来自哪里。

结论:协议选择服从数据流

REST与WebSocket不是替代关系。

REST适合无状态请求、控制面、历史查询、账户快照和断线恢复。它实现简单,天然适合缓存、网关和负载均衡。缺点是请求—响应模型带来重复请求和HTTP开销,不适合持续高频推送。

WebSocket适合实时行情、Tick、盘口和订单事件。它通过持久连接与全双工通信降低重复握手和头部开销。缺点是连接状态、重连、订阅恢复、消息完整性和本地状态一致性都需要客户端自行处理。

交易API接口选择的最终方案通常是混合架构:

  • 流平面使用WebSocket。
  • 控制平面使用REST。
  • 状态恢复使用REST快照与增量校验。
  • 执行平面根据柜台特性选择REST、WebSocket、FIX或专用API。
  • 高频路径不使用未经测量的通用协议替代专用接口。
  • 性能判断基于P99、吞吐、抖动、重连时间和数据完整性,而不是平均响应时间。

WebSocket在实时推送场景中最高可比REST提升98.5%,但这不是交易系统的通用收益率。加密货币数据流测试中的0.66秒至1.93秒重连时间,也不是所有平台的固定上限。

参数优化的边界很清楚。先保证状态可恢复,再降低通信延迟。先完成端到端测量,再决定是否更换协议。协议只是链路的一部分。真正决定交易系统性能的,是从数据生成到策略处理、从报单请求到柜台回报的完整路径。

相关阅读: 选择交易技术时要检查什么CTP API断线重连机制:如何防止量化系统在夜盘断网时漏单.

常见问题

REST和WebSocket在交易系统中分别适合做什么?
REST适合账户、持仓、权限、历史数据查询以及状态快照和断线恢复。WebSocket适合行情、Tick、盘口、成交和订单状态等持续事件推送。
WebSocket是不是一定比REST更快?
不一定。WebSocket主要减少连接复用和消息推送路径中的通信等待,服务端排队、风控、柜台处理、JSON解析和客户端阻塞仍可能成为瓶颈。
交易系统为什么要同时使用REST和WebSocket?
WebSocket负责持续传输事件,REST负责获取确定的状态快照、补充数据和校正本地状态。两者按执行、流、控制和恢复等系统平面分工,通常比单独使用一种接口更容易控制故障边界。
WebSocket断线后如何恢复交易状态?
客户端需要记录最后处理的消息序列号,重新建立连接并恢复订阅,再通过REST查询订单、持仓和资金快照,补齐增量事件或校正本地状态。恢复过程中还要检查消息顺序、去除重复消息并确认状态已经完整。
WebSocket下单是否天然优于REST下单?
不是。WebSocket可以减少请求层的连接和头部开销,但不会消除网关认证、风控检查、交易服务排队和柜台处理时间。下单接口应根据具体柜台协议、限流规则和端到端测量结果选择。