第三章 会话管理层:连接生命周期管理、心跳保活与断线重连策略

聊到会话管理,很多刚入行的同学会觉得——不就是发个心跳包嘛,有啥好讲的?

嗯,我当年也是这么想的。直到有一次线上事故,交易所那边连接断了,我们的网关却以为还活着,结果订单状态全乱了。那天晚上我盯着日志看到凌晨四点,才意识到会话管理远不止心跳那么简单。

3.1 连接生命周期:从出生到死亡

一个交易所连接,说白了就是一个TCP长连接。但它的生命周期,比你想的要复杂。

我个人习惯把连接分成四个阶段:

  • 初始化:创建socket,配置参数
  • 握手:TCP三次握手 + 应用层认证
  • 维持:正常收发数据 + 心跳保活
  • 关闭:主动断开或异常断开

每个阶段都有坑。我举个例子,初始化阶段很多人忽略了一个细节——TCP_NODELAY。默认情况下,Nagle算法会把小包攒起来再发,这对高频交易来说是致命的。你想想看,一个订单指令延迟了200毫秒才发出去,可能价格已经变了。

核心要点:每个连接必须维护一个状态机。从CONNECTING到CONNECTED,再到DISCONNECTED,状态转换必须严格校验。

3.2 心跳保活:别让交易所把你当死人

交易所那边有个机制——如果一段时间没收到你的消息,它就认为你挂了,然后主动断开连接。

这个时间窗口,不同交易所不一样。币安好像是30秒,OKX是15秒,火币我记得是20秒。嗯,这里要注意,千万别用同一个心跳间隔去适配所有交易所

我在项目中遇到过一个问题:某个交易所的文档写的是60秒超时,我们按50秒发心跳,结果线上频繁断连。后来抓包才发现,实际超时是45秒。所以我的建议是——心跳间隔设为文档值的60%,留足余量。

实战技巧:心跳包最好带上业务数据。比如把最新的行情时间戳塞进去,这样交易所那边也能校验你的数据是否滞后。

3.3 断线重连策略:别像个愣头青一样猛冲

连接断了怎么办?重连呗。

但怎么重连,这里面的门道可多了。

我曾经见过一个团队,断线后每秒重连一次,结果交易所那边直接把他们的IP封了——因为触发了反DDoS策略。

正确的做法是指数退避

class ReconnectStrategy:
    def __init__(self):
        self.base_delay = 1  # 初始延迟1秒
        self.max_delay = 60  # 最大延迟60秒
        self.attempt = 0
    
    def next_delay(self):
        delay = min(
            self.base_delay * (2 ** self.attempt),
            self.max_delay
        )
        # 加一点随机抖动,防止多个连接同时重连
        delay += random.uniform(0, 0.5)
        self.attempt += 1
        return delay
    
    def reset(self):
        self.attempt = 0

你看,第一次断线等1秒,第二次2秒,第三次4秒...最多等60秒。加上随机抖动,避免所有连接同时发起重连请求。

3.4 会话恢复:断线后别从头再来

重连成功后,最头疼的问题来了——之前的订单状态怎么办?

有些交易所支持会话恢复,比如FIX协议的ResetSeqNumFlag字段。但大部分交易所不支持,你得自己想办法。

我的做法是:

  1. 重连成功后,先查询所有未成交订单
  2. 对比本地缓存的订单状态
  3. 如果有不一致,以交易所为准
  4. 更新本地状态,然后继续交易

避坑指南:我曾经遇到过重连后查询订单接口返回超时,结果本地以为订单还在,实际上交易所那边已经撤单了。后来我加了一个超时重试+状态校验的机制,才彻底解决这个问题。

3.5 多连接管理:别让一个连接拖垮整个系统

一个网关通常要管理几十甚至上百个交易所连接。每个连接都有自己的生命周期、心跳、重连策略。

我建议用连接池来管理:

连接ID 交易所 状态 心跳间隔 重连次数
conn_001 币安 CONNECTED 15s 0
conn_002 OKX RECONNECTING 10s 3
conn_003 火币 DISCONNECTED 12s 5

每个连接独立运行,互不干扰。一个连接断了,不影响其他连接正常工作。

3.6 核心架构图

下面这张图,是我在实际项目中用的会话管理层架构。你看一眼就明白了:

会话管理层架构图 连接池 连接1 (币安) - CONNECTED 连接2 (OKX) - RECONNECTING 连接3 (火币) - DISCONNECTED 状态机 INIT → CONNECTING CONNECTING → CONNECTED CONNECTED → DISCONNECTED DISCONNECTED → RECONNECTING 心跳管理器 定时器: 每15秒 超时检测: 45秒 重连触发 重连策略 指数退避: 1s→60s 随机抖动: 0~0.5s 核心组件说明 连接池:管理所有交易所连接实例 状态机:严格校验每个连接的状态转换 心跳管理器:定时发送心跳,检测超时 重连策略:指数退避+随机抖动,避免风暴

3.7 总结一下

会话管理这块,说白了就是三件事:

  • 管好生命周期:状态机不能乱,每个阶段都要校验
  • 心跳要精准:间隔别太短也别太长,留足余量
  • 重连要优雅:指数退避+随机抖动,别把自己搞崩了

我记得有一次重构会话层,把原来混乱的状态机理清楚后,整个系统的稳定性提升了不止一个档次。嗯,这就是基本功的力量。