Bokeh如何检测session是否活跃 客户端关闭时停止流数据推送
Bokeh 会话活跃检测与断连停推实现方案
Bokeh 原生支持会话活跃状态检测,完全可以实现客户端关闭标签页/断开连接时自动停止后台流数据推送的需求,不需要额外引入第三方依赖。
核心实现逻辑
Bokeh 服务端为每个客户端连接维护独立的会话实例,内置WebSocket心跳机制检测连接状态,当客户端关闭标签页、页面刷新、网络中断导致连接断开时,会自动触发session_destroyed生命周期回调,你只需要在这个回调里终止对应会话的流推送线程即可,不需要自己实现心跳轮询。
具体实现代码
方式1:手动实例化Bokeh Server启动(适合自定义服务场景)
from bokeh.server.server import Server import threading import time # 全局存储每个会话对应的停止信号和工作线程,以会话ID为唯一键 session_task_map = {} def realtime_stream_worker(doc, stop_event): """后台流数据推送工作线程""" while not stop_event.is_set(): # 替换为你自己的实时数据拉取逻辑 latest_data = fetch_data_from_other_thread() # Bokeh文档更新必须通过next_tick回调提交,避免线程安全问题 doc.add_next_tick_callback(lambda: update_plot_datasource(latest_data)) time.sleep(0.1) # 匹配你需要的推送帧率 def handle_session_create(session_context): """新客户端连接建立时触发,启动对应流推送线程""" doc = session_context.document stop_event = threading.Event() worker_thread = threading.Thread( target=realtime_stream_worker, args=(doc, stop_event), daemon=True ) worker_thread.start() session_task_map[session_context.id] = (stop_event, worker_thread) def handle_session_destroy(session_context): """客户端断开、会话销毁时触发,停止对应流推送线程""" if session_context.id in session_task_map: stop_event, worker_thread = session_task_map.pop(session_context.id) stop_event.set() worker_thread.join(timeout=1) # 等待线程正常退出,避免僵尸线程 # 启动服务时绑定生命周期回调 server = Server( your_bokeh_apps, # 替换为你自己的Bokeh应用路由 on_session_created=handle_session_create, on_session_destroyed=handle_session_destroy, # 可选:调小心跳参数实现更快的断开检测,单位秒 websocket_ping_interval=1, websocket_ping_timeout=2 ) server.start()
方式2:通过bokeh serve命令行启动应用
如果是用命令行直接启动应用,不需要手动实例化Server,可以直接在当前文档上绑定销毁回调:
from bokeh.io import curdoc import threading doc = curdoc() stop_event = threading.Event() # 启动你的流推送工作线程,传入stop_event # stream_thread = threading.Thread(...) # stream_thread.start() def cleanup_on_disconnect(session_context): stop_event.set() # 绑定会话销毁回调 doc.on_session_destroyed(cleanup_on_disconnect)
避坑说明
- 禁止在工作线程中直接修改Bokeh的数据源、图表属性,所有更新操作必须通过
doc.add_next_tick_callback提交到Bokeh的主线程执行,否则会出现随机崩溃、数据不同步问题。 - 不要依赖前端JS的
beforeunload事件通知后端停止推送,浏览器崩溃、网络闪断时该事件不会触发,会导致后台僵尸线程堆积。 - 流推送的工作线程一定要设置为
daemon=True,避免服务退出时线程无法正常回收。 - 默认配置下Bokeh的心跳间隔是30秒,断开检测延迟较高,对流实时性要求高的场景可以手动调小
websocket_ping_interval参数,最快可以做到1-2秒内检测到断开并停止推送。
内容的提问来源于stack exchange,提问作者alex
相关产品推荐
相关产品推荐

