Skip to content

连接保活

WebSocket 行情推送是长连接服务。客户端需要正确处理 WebSocket 协议层的 ping/pong、网络超时、断线重连,以及重连后的重新鉴权和重新订阅。

WARNING

当前行情推送接口不定义业务层 JSON 心跳消息。请不要向连接发送自定义的 { "action": "heartbeat" }{ "type": "ping" } 等业务心跳帧,也不要依赖服务端返回某种 JSON 心跳事件。

连接保活应使用 WebSocket 协议层 ping/pong 能力,或使用客户端 SDK / WebSocket 库提供的连接状态、超时和重连机制。

Ping / Pong

WebSocket 协议本身支持 ping/pong 控制帧。不同运行环境的处理方式不同:

客户端类型建议
浏览器 WebSocket浏览器会在协议层自动响应服务端 ping。业务代码通常无法直接发送或监听协议层 ping/pong,只需要处理 openmessageerrorclose 等事件。
Node.js、Java、Go、Python 等服务端客户端优先使用 WebSocket 库内置的 ping/pong、读写超时和空闲检测能力。收到服务端 ping 时应及时返回 pong;如客户端库需要主动 ping,可按业务网络环境配置。
移动端或弱网络环境关注前后台切换、网络切换、系统省电策略导致的连接挂起。恢复网络后应检查连接状态,必要时重连。

平台不要求客户端发送某个固定 JSON 格式的心跳包。若你的 WebSocket 库支持协议层 ping,可以开启库自带的 ping/pong 机制;若运行环境不暴露协议层 ping,则应通过连接关闭事件和业务消息超时来判断连接是否可用。

定时刷新 Token

OAuth 2.1 签发的 Access Token 有有效期限制。为避免 token 过期导致连接被服务端主动断开,客户端应在 token 到期前定时刷新:

  1. 在获取 token 时记录 expires_in(有效期秒数)。
  2. 建议在 token 有效期过半或到期前 5 分钟时,使用 Refresh Token 获取新的 Access Token。
  3. 获取新 token 后,通过当前 WebSocket 连接重新发送登录鉴权消息,完成 token 更新。
  4. 如果刷新失败(例如 Refresh Token 也已过期),应引导用户重新授权。

TIP

定时刷新 token 是长连接保活的关键步骤。即使网络和 WebSocket 协议层 ping/pong 一切正常,token 过期后服务端仍会断开连接。

超时处理

长连接可能因为以下原因断开或变得不可用:

  • 本地网络切换、代理或防火墙中断连接。
  • 客户端进程休眠、移动端进入后台、系统回收网络资源。
  • 服务端发布、扩缩容或维护。
  • 连接长时间无有效读写,被中间链路或 WebSocket 库判定为空闲超时。

建议客户端实现以下超时策略:

  1. 连接建立超时:发起连接后,如果在合理时间内未进入 open 状态,应关闭本次连接并重试。
  2. 鉴权响应超时:连接建立后需要先完成登录鉴权。如果鉴权请求长时间没有响应,应关闭连接并重新建立。
  3. 订阅响应超时:订阅请求发出后,如果长时间未收到响应,应结合连接状态决定是否重试订阅或重连。
  4. 业务消息空闲检测:如果连接处于打开状态但长时间没有任何消息,应结合协议层 ping/pong、行情时段和订阅标的活跃度判断连接是否仍然健康。不要仅因非交易时段没有行情推送就立即判定连接失效。

具体超时时间请按客户端所在网络环境、产品实时性要求和 WebSocket 库能力设置。文档不承诺固定的公网 ping 间隔或超时阈值。

断线重连

收到 close 事件、连接异常、鉴权失败、订阅链路不可用或本地检测到连接失效时,客户端应重新建立 WebSocket 连接。

推荐重连流程:

  1. 停止向旧连接发送新请求。
  2. 清理旧连接的本地状态,例如正在等待响应的请求、连接对象、临时定时器等。
  3. 使用退避策略重新连接,避免短时间高频重试。
  4. 连接建立后重新登录鉴权。
  5. 鉴权成功后重新订阅当前业务仍然需要的标的和数据类型。
  6. 订阅恢复后,按需通过 REST 实时行情接口补齐最新状态。

建议使用指数退避或分段退避策略,例如首次断线后较快重试,连续失败后逐步增加等待时间,并设置最大重试间隔。不要在网络不可用或服务端持续拒绝时无限高频重连。

重新鉴权与重新订阅

WebSocket 订阅状态与当前连接会话相关。连接断开后,不应假设服务端仍然保留旧连接上的订阅状态。

每次重连后都应按以下顺序恢复:

text
建立 WebSocket 连接
  -> 登录鉴权
  -> 订阅 quote / order_book / ticker / kline 等数据
  -> 接收推送

注意事项:

  • 重连后必须重新鉴权。不要复用旧连接的会话状态。
  • 重连后必须重新发送订阅请求。客户端应在本地维护“当前业务需要订阅什么”,而不是依赖服务端恢复。
  • 如果访问凭证已经过期,应先刷新凭证,再重新建立连接或重新鉴权。
  • 如果重连期间用户已经离开页面或取消关注某些标的,不要恢复这些不再需要的订阅。
  • 订阅请求建议携带客户端生成的请求 id,便于将响应与本地待恢复任务对应起来。

结合 REST 获取首屏快照

WebSocket 推送更适合接收实时变化,不适合作为首屏完整状态的唯一来源。为了减少首次渲染等待时间,并避免在断线期间遗漏最新状态,建议在以下场景结合 REST 实时行情接口:

场景推荐做法
页面首次打开先调用 REST 获取行情快照或实时报价,快速渲染首屏;随后建立 WebSocket 连接并订阅实时推送。
断线重连成功后使用 REST 查询最新快照、买卖盘、当前 K 线或逐笔成交,再继续消费 WebSocket 推送。
长时间后台后恢复先检查连接是否仍然有效;如果发生重连,建议用 REST 补齐恢复时刻的最新状态。
对完整状态一致性要求高以 REST 查询结果作为某一时点的完整状态基线,再用 WebSocket 推送增量刷新。

相关 REST 接口可参考:

服务端会话清理

连接断开后,服务端会在后台识别离线连接并清理对应会话和订阅资源。该清理过程是服务端内部保护机制,用于释放离线连接占用的资源。

客户端不应依赖服务端清理时机来管理自身订阅状态:

  • 正常退出页面、切换标的或不再需要某类数据时,应主动发送反订阅请求。
  • 连接异常断开时,客户端应按重连流程重新鉴权并重新订阅,而不是等待旧会话恢复。
  • 不要假设旧连接上的订阅会在新连接中自动继承。
  • 不要依赖服务端会话清理完成后才重新订阅;新连接应作为新的独立会话处理。

客户端实现建议

建议客户端维护一份本地订阅意图表,用于记录当前业务真正需要的订阅项:

text
symbol + data_type + 可选参数(如 kline period / adjust)

连接恢复时,根据这份订阅意图表重新发送订阅请求。这样可以避免以下问题:

  • 断线后忘记恢复部分订阅。
  • 用户已经取消关注后仍然恢复旧订阅。
  • 多个页面或模块重复订阅同一标的,导致本地状态混乱。
  • 重连过程中无法区分哪些订阅响应对应当前连接。

同时建议:

  • 将连接状态展示给用户,例如“连接中”“实时行情已连接”“正在重连”。
  • 对连续重连失败设置告警或用户提示。
  • 对订阅失败、权限不足、配额不足等业务错误进行独立处理,不要简单地无限重连。
  • 页面关闭、组件卸载或业务不再需要时,主动反订阅并关闭连接。

常见误区

误区说明
发送 JSON 心跳包即可保活行情推送不定义业务层 JSON 心跳协议。应使用 WebSocket 协议层 ping/pong 或客户端库的连接保活能力。
断线后订阅会自动恢复不应这样假设。重连后应重新鉴权并重新订阅。
有 WebSocket 推送就不需要 RESTWebSocket 适合实时变化;首屏完整状态、断线补齐和一致性校准仍建议结合 REST。
没有行情推送就是连接断了非交易时段、标的不活跃或订阅类型本身更新频率低时,可能长时间没有业务推送。应结合协议层心跳和连接事件判断。
服务端清理旧会话后客户端才能重连客户端可以直接建立新连接并恢复订阅。服务端会自行清理离线会话资源。

下一步