如何使用Flask+SocketIO实现定时广播数据并支持启停控制?
使用Flask-SocketIO实现定时广播与停止功能
你原来的代码存在核心问题:time.sleep()会阻塞SocketIO的事件循环,导致整个服务响应能力下降,完全无法满足高性能要求。必须借助SocketIO自带的后台任务机制来实现,同时要为每个客户端的任务保留引用,才能支持精准停止操作。
实现思路
- 用
start_background_task()启动异步广播任务,避免阻塞主事件循环 - 通过客户端唯一标识
sid维护任务引用字典,追踪每个客户端的运行中任务 - 收到停止指令时,通过任务引用终止对应客户端的定时广播
完整示例代码
from flask import Flask from flask_socketio import SocketIO, emit, request import threading app = Flask(__name__) app.config['SECRET_KEY'] = 'your-secret-key' # 生产环境按需配置跨域,高性能场景建议用gevent/eventlet socketio = SocketIO(app, cors_allowed_origins="*", async_mode='gevent') # 存储客户端任务引用:key为sid,value为任务对象 active_tasks = {} # 共享数据锁,确保signal_list线程安全 signal_lock = threading.Lock() signal_list = [] # 你的业务数据 @socketio.on('startPolling') def start_polling(interval=0.5): sid = request.sid # 避免同一客户端重复启动任务 if sid in active_tasks: emit('notify', {'msg': '已有广播任务在运行'}) return def broadcast_loop(): while True: with signal_lock: # 广播最新数据到当前客户端 emit('signal_update', signal_list) # 用SocketIO异步睡眠,不阻塞事件循环 socketio.sleep(interval) # 启动后台任务并保存引用 task = socketio.start_background_task(broadcast_loop) active_tasks[sid] = task emit('notify', {'msg': f'广播已启动,间隔{interval}秒'}) @socketio.on('stopPolling') def stop_polling(): sid = request.sid if sid in active_tasks: # 终止后台任务 active_tasks[sid].stop() del active_tasks[sid] emit('notify', {'msg': '广播已停止'}) else: emit('notify', {'msg': '无运行中的广播任务'}) # 客户端断开时自动清理任务,防止内存泄漏 @socketio.on('disconnect') def clean_task_on_disconnect(): sid = request.sid if sid in active_tasks: active_tasks[sid].stop() del active_tasks[sid] if __name__ == '__main__': # 生产环境建议用gevent部署,而非自带的开发服务器 socketio.run(app, host='0.0.0.0', port=5000)
关键性能与可靠性注意事项
- 绝对禁用
time.sleep():必须使用socketio.sleep(),它是异步非阻塞的,不会影响其他客户端的请求处理 - 线程安全处理:如果
signal_list是多线程共享数据,必须加锁避免数据竞争 - 生产环境服务器选型:务必使用
gevent或eventlet作为异步服务器,Flask默认开发服务器性能极差,无法支撑高并发 - 自动清理机制:客户端断开时主动终止任务,防止无效任务占用内存
内容的提问来源于stack exchange,提问作者dymek662
相关产品推荐
相关产品推荐

