2、数据源接入层设计:交易所API对接、WebSocket协议详解、数据源认证与鉴权
数据源接入层,说白了就是整个实时行情管道的「水龙头」。
我做了这么多年数据架构,见过太多团队在接入层翻车——要么连不上交易所,要么连上了拿不到数据,要么拿到了数据发现是错的。嗯,这里面的坑,一个比一个深。
今天咱们就把这块掰开揉碎了讲。我会从交易所API对接讲起,再到WebSocket协议的核心细节,最后聊聊认证鉴权那些事。
2.1 交易所API对接:不止是调接口那么简单
每个交易所都提供API,但说实话,各家风格差异很大。我习惯把交易所API分成两类:
- REST API:一问一答,适合查账户、下单、拿快照数据
- WebSocket API:长连接推送,适合拿实时行情、成交回报
你想想看,如果做高频交易,用REST轮询拿行情,那基本等于开着拖拉机去赛车。所以实时行情这块,WebSocket是标配。
我在对接币安API时遇到过一个问题:它的REST接口返回的字段名是驼峰式,但WebSocket推送的字段名是下划线式。同一个交易所,两套命名规范。这种细节不注意,解析时就会出bug。
2.2 WebSocket协议详解:从握手到心跳
WebSocket本质上是一个应用层协议,建立在TCP之上。它解决了HTTP「请求-响应」模式的痛点——服务器没法主动给客户端发数据。
咱们来看一个典型的WebSocket连接建立过程:
// 客户端发起握手请求
GET /ws/stream HTTP/1.1
Host: api.exchange.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
// 服务器响应
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
握手成功后,连接就变成了全双工模式。这时候,客户端和服务器可以随时互发数据帧。
数据帧的结构是这样的:
| 字段 | 长度 | 说明 |
|---|---|---|
| FIN | 1 bit | 是否为最后一帧 |
| Opcode | 4 bits | 帧类型:0x1文本、0x2二进制、0x8关闭、0x9 ping、0xA pong |
| Mask | 1 bit | 客户端发数据必须为1,服务器发数据必须为0 |
| Payload Length | 7/7+16/7+64 bits | 数据长度,分三种情况 |
| Masking Key | 0 or 4 bytes | 掩码密钥,用于数据混淆 |
| Payload Data | 可变 | 实际数据内容 |
2.3 心跳机制:别让连接断了
WebSocket连接不是永久有效的。网络波动、服务器重启、防火墙超时,都可能导致连接断开。
我见过最典型的场景:某个团队对接火币的WebSocket,没有实现心跳重连。结果半夜网络抖动了一下,连接断了,第二天早上才发现行情停了6个小时。嗯,这个锅得架构师背。
心跳机制一般分两种:
- Ping/Pong帧:WebSocket协议自带的,客户端发Ping,服务器回Pong
- 应用层心跳:交易所自定义的,比如每隔30秒发一个空消息
我个人习惯两种都用。协议层心跳保活TCP连接,应用层心跳确认业务正常。
// 伪代码:心跳重连逻辑
while (true) {
if (ws.isConnected()) {
ws.sendPing();
Thread.sleep(30000); // 30秒一次心跳
} else {
ws.reconnect();
// 重连后重新订阅
ws.subscribe("btcusdt@trade");
}
}
2.4 数据源认证与鉴权:安全第一
交易所的API不是谁都能调的。尤其是涉及交易和私密数据的接口,必须做认证。
常见的认证方式有三种:
- API Key + Secret Key:最常用,但Secret Key不能明文传输
- JWT Token:适合分布式系统,但要注意Token过期时间
- OAuth 2.0:适合第三方应用授权,但实现复杂
拿API Key + Secret Key来说,签名过程一般是这样的:
// 签名生成步骤
1. 拼接参数字符串:timestamp + method + path + queryString
2. 用HMAC-SHA256加密,密钥是Secret Key
3. 将签名放在请求头中发送
// 示例(Python)
import hmac
import hashlib
def sign(timestamp, method, path, secret):
message = f"{timestamp}{method}{path}"
signature = hmac.new(
secret.encode(),
message.encode(),
hashlib.sha256
).hexdigest()
return signature
这里有个坑:时间戳必须和服务器时间同步。如果客户端时间偏差超过5秒,很多交易所会直接拒绝请求。我建议在启动时先调一次时间同步接口,把时间差校准。
2.5 多数据源接入策略
做实时行情,只接一个交易所是不够的。万一它挂了,你的整个系统就瘫痪了。
我建议至少接三个数据源:主数据源、备用数据源、校验数据源。主数据源负责日常数据,备用数据源在主数据源故障时切换,校验数据源用来交叉验证数据准确性。
下面这张图展示了多数据源接入的核心逻辑:
接入层的核心职责就是:统一管理所有WebSocket连接,处理心跳重连,把原始数据解析成统一格式,然后丢到消息队列里。
好了,数据源接入层这块就聊到这儿。核心就三件事:连得上、拿得到、拿得对。把这三点做好,你的实时行情管道就成功了一半。
公众号:蓝海资料掘金营,微信deep3321