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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 20:12:19