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

Flask-Socketio数据流15分钟后断开客户端,重连后推送失效求助

Flask-SocketIO 闲置15分钟后重连但数据流中断问题解决思路

问题现象

基于Flask+SocketIO+Eventlet构建的实时流Web应用,Chrome网页闲置约15分钟后,Web客户端和Python SocketIO客户端均收到断开连接事件;重连成功后,UI数据流完全停止更新。部署环境为IIS管理器。

核心流程回顾

DataStreamer.py(Python SocketIO客户端)→ 从外部WebSocket获取数据处理后,通过/web命名空间发送mydata事件到服务器 → 服务器更新Curve全局字典 → Web客户端加载时发送be事件触发后台任务CalculateBE,该任务每隔5秒计算Curve数据并通过bedata事件推送到UI → UI更新表格。

问题根源分析

  1. IIS进程回收+心跳配置不匹配:IIS默认15-20分钟闲置进程回收机制会重启Flask应用;当前ping_timeout=15过短,客户端与服务器心跳检测逻辑误判连接失效。
  2. 后台任务绑定失效:原后台任务绑定在旧连接实例上,重连后未重新触发任务,数据推送通道中断。
  3. 命名空间与重连逻辑错误:Web客户端未指定/web命名空间,重连后无法订阅事件;DataStreamer可能在连接未完全建立时发送事件,触发命名空间未连接错误。
  4. 线程锁未实例化:thread_lock = Lock未创建实例,导致后台任务线程安全控制失效,无法正确重启任务。

具体解决步骤

1. 调整IIS进程回收设置(关键)

  • 打开IIS管理器,找到对应应用池→高级设置
  • 禁用闲置超时(或延长至480分钟以上)
  • 禁用定期回收(或调整至低峰期)
  • 设置启动模式为AlwaysRunning,避免应用被闲置回收

2. 优化SocketIO心跳配置

修改__init__.py中的SocketIO初始化参数:

# __init__.py
from flask import Flask
from flask_socketio import SocketIO
from threading import Lock
import eventlet

eventlet.monkey_patch()
app = Flask(__name__, template_folder='./templates')
app.config['SECRET_KEY'] = 'privatekey!'

thread = None
thread_lock = Lock()  # 修复:实例化Lock
socketio = SocketIO(app, cors_allowed_origins='*', 
                    ping_timeout=60,  # 延长超时时间,避免误判
                    ping_interval=25,  # 每25秒发送心跳
                    logging=True)

3. 修复后台任务与重连触发逻辑

修改MydataClient.py,确保重连后自动重启任务:

# MydataClient.py
from wwwroot.StreamingApp import app, thread, thread_lock, socketio

Curve = None
live_be = []  # 确保全局变量初始化

def CalculateBE():
    while True:
        response = {'status': True}
        for args in live_be:
            if args is None:
                continue
            be_price = 0  # 替换为你的计算逻辑
            response['BE' + str(args[0])] = be_price
        # 指定命名空间发送,确保所有/web客户端接收
        socketio.emit('bedata', response, namespace='/web')
        socketio.sleep(5)

@socketio.on('be', namespace='/web')
def UpdateBE():
    global thread
    with thread_lock:
        # 检查任务是否存活,不存在则启动
        if thread is None or not thread.is_alive():
            thread = socketio.start_background_task(CalculateBE)

# 新增:web命名空间连接时自动触发任务
@socketio.on('connect', namespace='/web')
def on_web_connect():
    UpdateBE()

4. 修正Web客户端命名空间与重连逻辑

修改client.html中的JS代码,指定命名空间并在重连后重新触发任务:

<script>
$(document).ready(function () {
    // 明确连接/web命名空间
    var flask_socket = io.connect('http://localhost:90/web');
    
    flask_socket.on('connect', () => {
        console.log('connected!');
        // 重连后重新触发后台任务
        flask_socket.emit('be');
    });
    
    flask_socket.on('disconnect', () => {
        console.log('disconnected!');
    });
    
    flask_socket.on("bedata", function (response) {
        // 你的UI更新逻辑
        console.log('Received bedata:', response);
    });
});
</script>

5. 优化DataStreamer重连事件发送逻辑

确保DataStreamer在连接完全建立后发送事件:

# DataStreamer.py
import socketio

def on_connect():
    print("Connected to server")

def on_disconnect():
    print("Disconnected from server")

def on_reconnect():
    print("Reconnected to server")

sio = socketio.Client(reconnection_attempts=5, 
                      reconnection_delay=2, 
                      reconnection_delay_max=10)
sio.on('connect', on_connect)
sio.on('disconnect', on_disconnect)
sio.on('reconnect', on_reconnect)

# 连接指定命名空间
sio.connect('http://localhost:90', namespaces=['/web'])

# 在连接事件回调中处理数据发送,确保连接就绪
@sio.event(namespace='/web')
def connect():
    # 替换为你的数据获取与处理逻辑
    curve_data = {}
    sio.emit("mydata", curve_data, namespace="/web")

# 循环发送数据前检查连接状态
while True:
    if sio.connected and '/web' in sio.namespaces:
        curve_data = {}  # 实际数据
        sio.emit("mydata", curve_data, namespace="/web")
    sio.sleep(1)

验证步骤

  1. 重启IIS应用池和Flask服务
  2. 打开Web UI并保持闲置超过15分钟
  3. 检查客户端日志,确认重连后UI能正常接收bedata更新
  4. 检查DataStreamer日志,确保重连后无命名空间错误,mydata事件正常发送

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 07:35:57