Bokeh 服务端核心组件详解:bokeh.server.server 中 BaseServer、Server 与 bind_sockets 的完整指南

发布时间:2026/9/13 23:18:21

Bokeh 服务端核心组件详解:bokeh.server.server 中 BaseServer、Server 与 bind_sockets 的完整指南 Bokeh 服务端核心组件详解bokeh.server.server 中 BaseServer、Server 与 bind_sockets 的完整指南【免费下载链接】bokehInteractive Data Visualization in the browser, from Python项目地址: https://gitcode.com/GitHub_Trending/bo/bokeh本文围绕 Bokeh API 参考文档 server.rst 展开系统讲解bokeh.server.server模块提供的两个公开类BaseServer、Server以及辅助函数bind_sockets。读完后你将掌握如何在 Python 中以编程方式而非bokeh serve命令行启动、配置和关停一个 Bokeh 服务器包括监听地址/端口/Unix socket、多进程 worker、SSL 终结、WebSocket 来源白名单、会话Session查询以及如何通过Server.from_settings让程序化创建的服务端遵循与bokeh serve相同的环境变量约定。模块定位bokeh.server.server 是什么模块源码 的文档字符串说明了该模块的职责提供基于 TornadoHTTPServer与BokehTornado应用的服务端对象用于承载 Bokeh Server 应用Server Application。模块内公开的对象在__all__中被明确限定为三个server.py#L84-L88BaseServer轻量级协调类。它不替你创建任何组件而是要求你显式提供并协调好运行 Bokeh 服务器所需的三件套一个 TornadoIOLoop、一个BokehTornado应用实例、一个已经绑定到该应用的 TornadoHTTPServer。适合你已经在自行管理事件循环、需要精细控制进程/循环结构的场景。Server高层便捷类。只需要传入 Bokeh 的Application实例或应用路径到应用的映射、甚至一个可调用对象它会自动创建并协调上述底层 Tornado 组件。它还提供了工厂方法Server.from_settings可从 Bokeh 全局配置系统bokeh.settings.settings自动读取认证、SSL、会话签名、Cookie 等配置与bokeh serve命令的环境变量约定保持一致。bind_sockets开发辅助函数将 socket 绑定到指定端口也兼容操作系统自动分配端口的情况见下文。模块文档同时指向用户指南中的ug_server_introduction章节获取 Bokeh server 的整体背景信息。需要说明的边界是Server这个高层类存在明确限制——不能同时设置显式的io_loop和num_procs 1若要在这两个维度上同时自由必须改用BaseServer手动协调三个组件。Server一次讲全构造参数与全部可配置项Server的构造函数签名为server.py#L420-L421def __init__(self, applications, io_loopNone, http_server_kwargsNone, **kwargs)applications三种传入形态applications参数接受三种形态这是编写多应用服务器的关键URL 路径到Application的映射dict[str, Application]每个应用由一个对应 URL 的路径标识如/或/myapp单个Application会被自动映射到根路径/一个可调用对象作为便捷方式会用FunctionHandler为它创建一个Application。Application本质上是 Document 的工厂每个 Session 会初始化一个全新的 Document。单元测试 test_server__server.py#L285-L297 中的test_server_applications_callable_arg直接验证了可调用对象形态把modify_doc传给服务器后请求url取回会话并断言session.document.title Hello, world!并验证了{/foo: modify_doc}映射形态下/foo路径的行为一致。http_server_kwargs 与 io_loopio_loop可选显式指定运行 Bokeh Server 代码的 TornadoIOLoop为None时使用IOLoop.current()。源码中有一个值得注意的实现细节IOLoop 只能在HTTPServer.start()调用之后再引用代码注释指向 issue #5524见 server.py#L530-L532。http_server_kwargs可选原样传递给tornado.httpserver.HTTPServer的额外参数例如max_buffer_size用于限制最大上传体积。_ServerOpts全部服务端选项一览其余关键字参数由私有的_ServerOpts(Options)类解析server.py#L668API 文档中的选项即来源于此。以下按源码逐项继承其说明并补充默认值与实现事实参数类型/默认值说明继承自源码 help 文本num_procsint默认1HTTP 服务器启动的 worker 进程数。若同时配置了显式io_loop则只能取 1取 0 表示自动检测 CPU 核数。注意受 Tornado 限制Windows 不支持num_procs 1——官方建议在这种情况下运行多个 Bokeh server 实例放在负载均衡器之后。addressstr \| None服务器监听 HTTP 请求的地址。portint默认DEFAULT_SERVER_PORT监听端口。该默认值来自全局配置resources.py#L75 中DEFAULT_SERVER_PORT settings.default_server_port()而 settings.py#L817 显示其底层默认值为5006且支持环境变量BOKEH_DEFAULT_SERVER_PORT覆盖。unix_socketstr \| None要绑定的 Unix socket。与port、address、SSL 选项等其他网络参数不兼容且 Windows 上不可用。prefixstr默认用于所有 Bokeh server 路径的 URL 前缀。测试test_prefixtest_server__server.py#L152-L158验证了传prefixfoo后server.prefix /foo注意自动补了前导斜杠。indexstr \| None用于索引页/的 Jinja2 模板路径。allow_websocket_originlist[str] \| None允许连接 WebSocket 的主机列表。当使用bokeh.embed.server_document等机制把 Bokeh 应用嵌入外部网站时通常需要设置为None时默认使用localhost。use_xheadersbool默认False是否让 Bokeh server 用X-Real-Ip、X-Forwarded-For、X-Scheme、X-Forwarded-Proto请求头若提供覆盖所有请求的远端 IP 与 URI scheme/协议。这是放在反向代理后面部署的关键开关。ssl_certfilestr \| NoneSSL 终结所用的证书文件路径。ssl_keyfilestr \| NoneSSL 终结所用的私钥文件路径。ssl_passwordstr \| None必要时用于解密 SSL keyfile 的密码。websocket_max_message_sizeint默认DEFAULT_WEBSOCKET_MAX_MESSAGE_SIZE_BYTES设置 Tornado 的websocket_max_message_size值该常量定义于 tornado.py。构造期的参数校验server.py#L466-L477值得单独强调因为它们直接抛RuntimeErrornum_procs 1且显式传了io_loop报错提示改用BaseServer协调显式 IOLoop 与多进程 HTTPServernum_procs 1且平台为 Windows直接拒绝unix_socket非空且平台为 Windows直接拒绝。此外还有两条从源码结构看值得了解的隐含约束使用unix_socket时_address/_port会被置为Noneserver.py#L490-L493而num_procs ! 1时源码会断言所有已注册应用都满足application_context.application.safe_to_fork即用户应用代码不能在启动多进程之前执行过否则视为不安全操作server.py#L515-L518。一个可运行的完整示例综合上述参数一个典型的程序化服务器如下from bokeh.application import Application from bokeh.server.server import Server def modify_doc(doc): doc.title Hello, Bokeh Server # 单应用 - 自动映射到 /; 也可用 {path: Application(...}} 多应用 app Application(modify_doc) server Server( app, address0.0.0.0, port5006, # 默认即 DEFAULT_SERVER_PORT (5006) allow_websocket_origin[localhost:8000, my-website.com], use_xheadersTrue, # 放在 Nginx 等反向代理后时开启 # ssl_certfilecert.pem, # ssl_keyfilekey.pem, # num_procs2, ) server.show(/) # 仅本地测试时使用生产部署不应调用 server.run_until_shutdown()Server.from_settings与 bokeh serve 环境变量约定对齐的工厂方法Server.from_settingsserver.py#L536-L638是类方法作用为未显式以关键字参数传入的配置自动从全局settings模块补齐从而使程序化创建的服务端与bokeh serve命令遵循相同的环境变量约定。其参数与默认来源如下参数未传入时的默认来源applications/io_loop/http_server_kwargs同Server.__init__auth_providersettings.auth_module()指向的路径加载为AuthModule未配置路径时使用NullAuthsecret_keysettings.secret_key_bytes()sign_sessionssettings.sign_sessions()ssl_certfile/ssl_keyfile/ssl_passwordsettings.ssl_certfile()/settings.ssl_keyfile()/settings.ssl_password()cookie_secretsettings.cookie_secret()xsrf_cookiessettings.xsrf_cookies()ico_pathsettings.ico_path()自定义 favicon.ico文件路径其余关键字参数原样转发给Server。该方法会抛ValueError的情况是sign_sessionsTrue但拿不到secret_keyserver.py#L623-L624。单元测试对该方法做了两条直接验证test_server__server.py#L361-L405test__from_settings_uses_envvarsmock 掉settings后断言Server.from_settings(Application())确实把auth_providerAuthModule实例、sign_sessions、secret_key、SSL 三件套、cookie_secret、xsrf_cookies全部透传进了Server.__init__test__from_settings_kwarg_overrides_envvar显式传入的auth_providernull_auth会覆盖环境变量级别的设置。即优先级明确显式关键字参数 settings/环境变量。BaseServer手动协调 IOLoop、BokehTornado 与 HTTPServer当你需要把 Bokeh 服务器嵌入自己已有的事件循环例如与其他 asyncio 服务共存、或在测试中精确控制循环生命周期时使用BaseServer。其构造函数server.py#L123要求三个参数io_loop运行 Bokeh Tornado 应用的 TornadoIOLooptornado_appBokehTornado实例即生成 Bokeh Document 与 Session 的服务端机制本体http_server处理 HTTP 请求的 TornadoHTTPServer必须已经在使用tornado_app创建时就配置好。BaseServer的构造过程只做一件事在这三个对象上调用self._tornado.initialize(io_loop)把BokehTornado初始化到给定循环上。最小用法与 test_server__server.py#L267-L283 的test_base_server完全一致from bokeh.application import Application from bokeh.server.server import BaseServer from bokeh.server.tornado import BokehTornado from tornado.httpserver import HTTPServer from tornado.ioloop import IOLoop loop IOLoop() loop.make_current() app BokehTornado(Application()) httpserver HTTPServer(app) httpserver.start() server BaseServer(loop, app, httpserver) server.start() # ... 你的代码 ... httpserver.stop() server.stop() loop.close()生命周期方法逐个拆解start()把 Bokeh Server 及其后台任务安装到IOLoop上。源码文档明确强调此方法不阻塞、也不影响IOLoop的状态循环的启停必须由你自己负责——它适用于你本就在显式管理IOLoop的情形。stop(waitTrue)停止并移除所有 Bokeh Server 的IOLoop回调并停止其配置的HTTPServer。wait控制是否等待有序清理。这里有一个从源码结构看很有意思的并发细节server.py#L175-L214同步调用无法阻塞服务器自身正在运行的事件循环因此当检测到调用发生在服务器所运行循环的线程内时清理会被调度为任务并立即返回此时需要await wait_until_stopped()作为完成屏障异步调用方则应直接使用stop_async()。stop_async()从异步代码中停止服务器并等待有序的应用清理。当你后续的工作依赖于所有会话与生命周期钩子都执行完毕时应使用它而不是stop。与stop一样只能调用一次。wait_until_stopped()等待由stop在同一事件循环内调度的清理任务完成即上面提到的完成屏障。unlisten()停止监听端口调用后服务器不再可用。文档注明该方法主要用于测试。run_until_shutdown()在Server层最常用的启动并常驻方式。它会若尚未start()则先启动通过atexit.register安装进程退出钩子在非 Windows 平台上为事件循环注册SIGTERM信号处理器_sigterm会打印Received signal SIGTERM, shutting down并让loop.start()返回然后调用self._loop.start()进入阻塞。捕获KeyboardInterrupt即 Ctrl-C后打印Interrupted, shutting down并执行self.stop()。也就是说它同时响应 Ctrl-C 与 SIGTERM 两种关停方式server.py#L250-L275。会话与运行信息访问BaseServer还提供了一组查询属性/方法常用于运维脚本或测试get_session(app_path, session_id)按应用路径与会话 ID 取一个活动会话返回ServerSessionget_sessions(app_pathNone)取所有应用当前活动的会话给定app_path时只取该应用的。测试test_get_sessionstest_server__server.py#L168-L212验证了完整行为每发起一次 HTTP 请求对应路径的会话数加一get_sessions()不带参数时汇总全部应用对不存在的app_path则抛ValueErrorshow(app_path, browserNone, newtab)在浏览器窗口或标签页中打开应用。app_path必须以/开头否则抛ValueErrornew可选tab或windowbrowser可指定如firefox等语义同标准库webbrowser。源码文档明确提醒此方法适合本地测试生产部署中不应调用port/address属性BaseServer的实现是从HTTPServer实际绑定的 socket 中读取真实监听值server.py#L366-L384而Server子类则直接返回构造期记录的_port/_address——在使用unix_socket时Server.port/address为None并有专门的unix_socket属性。Server.port的返回值类型是int | None这保证了bind_sockets在端口为 0由 OS 自动分配时仍能给出真实端口prefix/index属性透传BokehTornado上配置的 URL 前缀与索引模板路径。bind_sockets端口绑定的开发辅助函数bind_sockets(address, port)server.py#L94-L103实现很短但行为上有两个要点def bind_sockets(address: str | None, port: int) - tuple[list[socket.socket], int]: Bind sockets to one port, including when the OS selects the port. sockets netutil.bind_sockets(portport or 0, addressaddress) ... return sockets, actual_port支持port0让操作系统自动选择端口绑定后会从所有 socket 的getsockname()中反解出真实端口actual_port保证所有 socket 落在同一端口上否则断言失败显式端口时做一致性断言如果调用方指定了端口会断言实际端口必须与之一致。Server.__init__在走 TCP/IP 路径时正是调用bind_sockets(opts.address, opts.port)完成绑定的server.py#L499这也是测试中常用port0启动临时服务器而不产生端口冲突的原因如test_server_applications_callable_arg。SSL 终结与 WebSocket 来源白名单的实现细节SSL 终结当ssl_certfile有值时Server会在日志中记录Configuring for SSL termination然后创建ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)并load_cert_chain(certfile..., keyfile..., password...)把上下文放入http_server_kwargs[ssl_options]server.py#L483-L488。单元测试test_ssl_args_plumbingtest_server__server.py#L251-L265用 mock 验证了 cert/key/password 三个参数确实被原样传给load_cert_chain。WebSocket 来源白名单allow_websocket_origin会经create_hosts_allowlist定义于 util.py转换为允许的主机列表并作为extra_websocket_origins传给BokehTornado非 Unix socket 场景下白名单中会带上实际端口号server.py#L494-L502。这解释了为什么嵌入外部站点时必须显式列出页面所在域名。X-Forwarded 处理use_xheaders通过http_server_kwargs.setdefault(xheaders, ...)注入HTTPServer测试test_use_xheaders断言server._http.xheaders is Truetest_server__server.py#L246-L249。相关模块与延伸阅读bokeh.server.server只是 Bokeh 服务端的入口层从源码的导入与引用关系看可以沿以下路径继续深入均为仓库内相对路径src/bokeh/server/tornado.pyBokehTornado应用本体负责路由、Document/Session 生成与websocket_max_message_size等机制src/bokeh/server/session.pyServerSessionget_session(s)的返回类型src/bokeh/server/auth_provider.pyNullAuth、AuthModule、AuthProviderfrom_settings认证参数的类型来源src/bokeh/command/subcommands/serve.pybokeh serve命令行子命令其选项与_ServerOpts的对应关系对应 API 参考页server.rst 由 Sphinxautomodule指令渲染本模块全部成员文档本文对其内容逐项继承并结合源码扩充同目录还有 tornado.rst、session.rst 等参考页。小结bokeh.server.server用两个层次清晰的类覆盖了 Bokeh 服务端的两种使用姿势Server面向绝大多数场景——传一个Application或路径映射、可调用对象加上一组_ServerOpts选项端口默认 5006、num_procs多进程、SSL、WebSocket 白名单、URL 前缀等必要时用from_settings对齐bokeh serve的环境变量约定最后run_until_shutdown()常驻并以 Ctrl-C/SIGTERM 优雅退出BaseServer则面向需要自管IOLoop的嵌入场景配合start/stop/stop_async/wait_until_stopped/unlisten提供精确的生命周期控制。约束Windows 不支持多进程、unix_socket与网络参数互斥、sign_sessions必须有secret_key在源码中均以显式异常表达测试套件 tests/unit/bokeh/server/test_server__server.py 对其中大部分行为提供了可直接复现的验证用例。【免费下载链接】bokehInteractive Data Visualization in the browser, from Python项目地址: https://gitcode.com/GitHub_Trending/bo/bokeh创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/9/13 23:18:21

遥感图像融合经典算法:IHS变换原理、实现与参数调优

简介:面向遥感图像处理初学者、课程设计及科研人员,这份MATLAB资源围绕HIS/IHS色彩空间变换,演示如何把多光谱与全色影像进行融合,以提升空间分辨率同时保留光谱信息。压缩包共7个文件,包括4幅TIFF格式测试影像&#x…

2026/9/13 23:58:22

python全栈考试作业 2017-03-30

2017年3月31日1、执行 脚本的两种方式(1)指令行加上文件, 名为hello.py, 通过运用全局变量来阐释这个脚本, 默认输入值是2, 要是有输入的话, 输入值则变为3。(2)下达指令, 于命令行输入“./”加上文件, 文件为“vim hello.py”, 此步骤是默认头部指定“#!/usr/bin/env”, 接着要…

2026/9/13 23:58:22

企业AI框架选Java还是Python

针对企业开展AI开发来说, 首先碰到的技术选型环节里那个绕不过去的问题便是, 是选用Java, 还是别的什么。此问题于小型企业或许并非难题, 因为其生态多样、容易上手且社区资源颇丰来着。然而在具备一定规模的Java企业当中,这可是个实实在在的工程问题。该Java领域的AI生态的确是…

2026/9/13 23:58:22

屠龙少年终成恶龙,前端转产品的我给前端挖了个坑

从前端转向产品大概三周左右, 借由《我转产品了 - 前端转产品是种怎样的体验》这篇文章, 将自身的一些感受分享给大家, 评论区突然出现好多厉害的人。因较为忙碌, 不知不觉间似乎一下子又过去了一个多月, 此次趁着周末没开成会议, 给大家讲讲最近的“有意思但又很奇特的事”。当…

2026/9/13 23:53:22

Python 中的布尔类型(bool):深入解析与高效使用

中的布尔类型(bool):深入解析与高效使用对于布尔类型(bool)而言, 它是一种基础的数据类型, 存在于特定范畴的编程环境里, 表示一种逻辑意义的真和假。布尔这个值, 在多个编程场景当中有着广泛的应用, 比如条件判断的相…

2026/9/13 0:01:16

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/12 6:29:36

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/12 14:32:17

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/13 11:18:28

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码