You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python对接OKX API的WebSocket异常及数据库存储问题排查

问题排查与解决方案

一、WebSocket连接莫名断开的原因及修复

核心原因

  1. 缺少心跳维持:OKX WebSocket服务器会主动断开长时间无交互的连接,若未定时发送心跳包,连接会被回收。
  2. 无自动重连机制:网络波动、服务器限流/会话超时等场景下,连接断开后无法自动恢复。
  3. 未处理服务器主动断开的信号:OKX可能因API权限、请求频率超限等原因主动断开连接,未捕获这类场景。

解决方案

  1. 启用内置心跳机制:
    在run_forever()中配置ping_interval和ping_timeout,让websocket-client自动发送心跳:

    ws.run_forever(ping_interval=30, ping_timeout=10)
    

    (OKX要求心跳间隔不超过30秒,此处设置30秒发一次ping,10秒未收到pong则判定超时)

  2. 实现指数退避重连:
    在on_close和on_error中添加重连逻辑,避免频繁重试导致被限流:

    import time
    
    def on_close(ws, close_status_code, close_msg):
        print(f"WebSocket closed: {close_status_code} - {close_msg}")
        reconnect()
    
    def on_error(ws, error):
        print(f"WebSocket error: {error}")
        reconnect()
    
    def reconnect():
        retry_count = 0
        while True:
            try:
                # 指数退避:间隔1s→2s→4s→…→最大60s
                sleep_time = min(2 ** retry_count, 60)
                print(f"Reconnecting in {sleep_time}s...")
                time.sleep(sleep_time)
                
                # 重新初始化WebSocket连接
                new_ws = websocket.WebSocketApp(
                    url="wss://ws.okx.com:8443/ws/v5/private",
                    on_open=on_open,
                    on_message=on_message,
                    on_error=on_error,
                    on_close=on_close
                )
                new_ws.run_forever(ping_interval=30, ping_timeout=10)
                break
            except Exception as e:
                print(f"Reconnect failed: {e}")
                retry_count += 1
    
  3. 检查API合规性:

    • 确保API密钥权限正确(需钱包相关权限)
    • 核对请求频率是否符合OKX WebSocket的限制,避免因超限被断开。

二、psycopg2异常适配错误与连接池耗尽的修复

核心原因

  1. 异常对象无法直接存入PostgreSQL:psycopg2默认不支持将WebSocketConnectionClosedException这类自定义异常对象作为参数插入数据库,会触发ProgrammingError。
  2. 连接未正确归还:错误处理逻辑中若发生异常,可能导致连接池的连接未被putconn()归还,长期积累后连接池耗尽,触发PoolError。

解决方案

  1. 将异常转换为字符串存储:
    记录错误时,不要直接传入异常对象,而是用traceback.format_exc()获取完整错误栈(或str(error)获取简单描述):

    import traceback
    
    def log_error(error):
        # 获取完整错误栈字符串
        error_detail = traceback.format_exc()
        conn = None
        try:
            conn = pool.getconn()
            with conn.cursor() as cur:
                # 确保数据库表的error_message字段是TEXT类型
                cur.execute(
                    "INSERT INTO error_logs (error_time, error_message) VALUES (NOW(), %s)",
                    (error_detail,)
                )
            conn.commit()
        except Exception as db_err:
            print(f"Failed to log error: {db_err}")
            if conn:
                conn.rollback()
        finally:
            # 无论是否成功,必须归还连接到池
            if conn:
                pool.putconn(conn)
    
  2. 强制保证连接回收:
    使用try-finally结构包裹连接的获取与使用,确保即使发生数据库操作异常,连接也能被归还到池中,避免连接泄漏。

  3. 优化连接池配置:
    若业务量较大,可适当调整连接池的minconn和maxconn参数,但需注意PostgreSQL的最大连接数限制(默认通常是100):

    from psycopg2 import pool
    
    # 初始化连接池,根据业务调整参数
    connection_pool = pool.SimpleConnectionPool(
        minconn=2,
        maxconn=10,
        dbname="your_db",
        user="your_user",
        password="your_pwd",
        host="your_host"
    )
    

内容的提问来源于stack exchange,提问作者Filips

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 05:22:25