如何基于Jupyter内核自研NoteBook
简介自研NoteBook如何高效地管理 Jupyter Kernel 的生命周期、处理代码执行请求以及实现实时的消息推送是其中的核心。本文将分享一套基于微服务架构的 Jupyter 内核管理系统的设计思路和实现方案。租户Jupyter服务管理1.使用miniforge管理python的依赖包2.每个租户单独启动一个pod启动对应的jupyter服务启动命令如下/local/.miniforge3/bin/jupyter labextension disable jupyterlab/docmanager-extension:download /local/.miniforge3/bin/jupyter labextension disable jupyterlab/filebrowser-extension:download /local/.miniforge3/bin/jupyter labextension disable jupyterlab/docmanager-extension:open-browser-tab /local/.miniforge3/bin/jupyter labextension disable jupyterlab/filebrowser-extension:open-browser-tab //local/.miniforge3/bin/jupyter-lab --ServerApp.ip* --ServerApp.password --ServerApp.token --no-browser --allow-root --port8888 --NotebookApp.base_url/web/${IDE_CR_NAME}/jupyter --NotebookApp.disable_check_xsrfTrue整体架构系统采用微服务架构将功能拆分为多个独立的服务模块各司其职,核心组件职责- **Web 服务层**: 提供 REST API 和 WebSocket 服务处理前端请求管理用户会话- **Gateway 层**: 作为中间层管理内核连接池转发消息实现与 Jupyter Server 的解耦- **资源管理器**: 负责内核的路由和负载均衡决定将请求分发到哪个 Gateway 实例- **Jupyter Kernel**: 实际执行代码的计算内核一个pod部署一套jupyter服务技术选型- **后端框架**: Spring Boot- **数据持久化**: MyBatis MySQL- **实时通信**: WebSocket (JSR-356)- **消息中间件**: Redis Pub/Sub- **协议标准**: Jupyter Messaging Protocol 5.2概念解释1.Kernel (内核)Kernel 是 Jupyter 生态系统的核心它是一个独立的进程负责执行用户提交的代码。每个 Kernel 都运行在独立的进程中拥有自己的内存空间和执行环境。Kernel 的特点:- **语言特定**: 每个 Kernel 对应一种编程语言如 Python Kernel、Scala Kernel、Java Kernel 等- **状态保持**: Kernel 在运行期间会保持执行状态变量、函数、导入的模块等都会保留在内存中- **独立进程**: 每个 Kernel 都是独立的进程互不干扰一个 Kernel 崩溃不会影响其他 Kernel- **生命周期管理**: Kernel 可以被创建、启动、停止、重启和删除Kernel 的状态:- idle: 空闲状态等待执行代码- busy: 正在执行代码- starting: 正在启动中- dead: 已停止或崩溃**示例场景**:python # 在 Python Kernel 中执行 x 10 y 20 print(x y) # 输出: 30 # 变量 x 和 y 仍然保留在 Kernel 的内存中 # 后续的代码可以继续使用这些变量Session (会话)Session 在 Jupyter 中有两层含义1. **WebSocket Session**: 客户端与服务器之间的 WebSocket 连接会话2. **Jupyter Session**: Jupyter 协议中的会话标识用于关联请求和响应WebSocket Session:- **连接会话**: 前端通过 WebSocket 与后端建立的长连接- **双向通信**: 支持客户端和服务器之间的双向实时通信- **状态管理**: 每个 Session 都有唯一的标识符用于管理连接状态- **生命周期**: Session 从连接建立开始到连接关闭结束Jupyter Session:- **消息关联**: Jupyter 协议中每个消息都有一个 session 字段用于将请求和响应关联起来- **执行上下文**: 通常使用 Cell ID 作为 Session ID这样可以将执行结果与特定的代码单元关联- **消息追踪**: 通过 Session ID 可以追踪一次代码执行的所有相关消息**Session 的作用**:前端发送执行请求↓消息头中包含 session: cell-123↓Kernel 执行代码并返回结果↓响应消息中也包含相同的 session: cell-123↓前端可以根据 session 将结果匹配到对应的代码单元Cell (代码单元)**什么是 Cell**Cell 是 Notebook 中的基本组成单位是用户编写和执行代码的容器。**Cell 的类型**:- **Code Cell**: 代码单元包含可执行的代码- **Markdown Cell**: 文档单元用于编写说明文档- **Raw Cell**: 原始文本单元不会被执行**Cell 的生命周期**:创建 Cell↓编辑代码内容↓执行 Cell (发送到 Kernel)↓Kernel 执行代码↓返回执行结果↓显示结果 (输出、错误、状态等)↓保存执行历史Cell 的执行状态:- idle: 未执行或执行完成- running: 正在执行中- queued: 等待执行- error: 执行出错Cell 与 Kernel 的关系- 一个 Notebook 可以绑定一个 Kernel- 一个 Kernel 可以执行多个 Cell 的代码- Cell 的执行是顺序的但可以通过异步机制实现并发- 所有 Cell 共享同一个 Kernel 的执行环境变量、函数等**示例**:python# Cell 1import pandas as pddf pd.DataFrame({A: [1, 2, 3]})# Cell 2 (可以访问 Cell 1 中定义的变量)print(df.head()) # 输出 DataFrame 的前几行内核创建流程详解完整请求流程关键设计点内核创建接口**接口设计**:http POST /api/kernel/bind Content-Type: application/json { kernelName: python3, notebookId: notebook-uuid } **响应示例**:json { code: 0, data: { kernelId: kernel-uuid, status: idle } } 2.2.2 内核规格查询系统支持查询可用的内核类型前端可以根据此信息展示内核选择界面http GET /api/kernel/specs 返回所有已注册的内核规格包括 Python、Scala、Java 等。Session 管理机制3.1 双层 Session 架构系统采用双层 Session 管理将用户会话和内核会话分离3.1.1 用户级 WebSocket Session**连接端点**: ws://host/api/user/{userId}**职责**:- 用户级别的消息推送通道- 接收前端发送的业务请求- 通过 Redis Pub/Sub 接收系统推送的消息**Session 管理**:java// 使用线程安全的 Map 存储活跃的 WebSocket Sessionprivate static final MapString, Session SESSIONS_MAP new ConcurrentHashMap();// 在线用户计数private static final AtomicInteger ONLINE_COUNT new AtomicInteger(0);**关键特性**:- **自动订阅**: 连接建立时自动订阅用户专属的 Redis Channel- **心跳检测**: 支持心跳机制保持连接活跃- **优雅关闭**: 连接关闭时自动清理资源和监听器#### 3.1.2 内核级 WebSocket Session**连接端点**: ws://host/api/kernel/{kernelId}**职责**:- 内核级别的消息推送通道- 接收内核执行结果的实时推送- 每个内核有独立的订阅通道Gateway 层连接池管理Gateway 层维护一个 WebSocket 连接池管理所有与 Jupyter Kernel 的连接Service public class WebSocketPool { // 内核ID - WebSocket连接的映射 private final static MapString, WebSocketConnection connectionMap new ConcurrentHashMap(); public void addConnection(String kernelId, WebSocketConnection connection) { connectionMap.put(kernelId, connection); } public WebSocketConnection getConnection(String kernelId) { return connectionMap.get(kernelId); } public static void removeConnection(String kernelId) { connectionMap.remove(kernelId); }核心 API 设计内核管理 API| /api/kernel/specs | GET | 获取可用内核列表 || /api/kernel/list | GET | 获取运行中的内核列表 || /api/kernel/bind | POST | 创建并绑定内核到 Notebook || /api/kernel/delete | DELETE | 删除内核 |代码执行 API| /api/cell/add | POST | 添加新的代码单元 || /api/cell/save | POST | 保存代码单元内容 || /api/cell/run | POST | 执行代码单元 || /api/cell/result | GET | 获取执行结果 |Gateway 层 API| /api/gateway/kernel/create | POST | 创建内核实例 || /api/gateway/kernel/connect | POST | 建立 WebSocket 连接 || /api/gateway/message/send | POST | 发送代码执行请求 || /api/gateway/kernel/status | GET | 检查内核状态 |连接池管理Gateway 层维护 WebSocket 连接池避免重复创建连接java WebSocketConnection connection pool.getConnection(kernelId); if (connection null) { connection new WebSocketConnection(kernelId, endpoint); pool.addConnection(kernelId, connection); }

相关新闻

有可能我已经彻底解决了自动化异常停止

有可能我已经彻底解决了自动化异常停止

因为如果打开的动作没有响应,就会导致发生异常,后面的自动打开代码全都会被跳过--------------------这就能解释:明明我有自动检测的部分,为什么没有效果。现在应该是正常了--------概率70%-----------------------意思就是&#…

2026/10/13 1:41:59 阅读更多 →
Android老项目构建失败:Gradle版本降级与兼容性配置实战指南

Android老项目构建失败:Gradle版本降级与兼容性配置实战指南

1. 老项目迁移的“版本墙”困境 如果你手头有一个两三年前,甚至更早的Android项目,想在最新的Android Studio上打开,大概率会遭遇一场噩梦。最常见的场景就是:你满怀期待地导入项目,结果IDE底部的Build窗口开始疯狂报…

2026/10/13 2:21:41 阅读更多 →
Umi-OCR:3步解决你所有的文字识别难题,完全离线保护隐私

Umi-OCR:3步解决你所有的文字识别难题,完全离线保护隐私

Umi-OCR:3步解决你所有的文字识别难题,完全离线保护隐私 【免费下载链接】Umi-OCR OCR software, free and offline. 开源、免费的离线OCR软件。支持截屏/批量导入图片,PDF文档识别,排除水印/页眉页脚,扫描/生成二维码…

2026/10/13 2:22:03 阅读更多 →

最新新闻

lingbot-map:室内移动机器人激光SLAM建图与导航实战

lingbot-map:室内移动机器人激光SLAM建图与导航实战

看到“lingbot-map”这个项目名,我第一反应就是机器人地图相关,而且大概率是围绕建图、定位、导航这三件套来做文章。我实际接触过不少类似的室内移动机器人项目,名字里带“bot”的通常都是机器人本体的代号,“map”则明确指向地图…

2026/10/13 7:58:24 阅读更多 →
无模型控制仿真:MFAPC与MFAILC实现、对比与工程避坑指南

无模型控制仿真:MFAPC与MFAILC实现、对比与工程避坑指南

1. 从模型依赖到数据驱动:MFAPC与MFAILC想要解决的问题做控制的都知道一个尴尬的事实:课本上那些漂亮的控制器设计方法,到了现场十有八九要先过“建模”这一关。经典PID要整定参数,极点配置要拿到状态空间模型,模型预测…

2026/10/13 7:58:24 阅读更多 →
深入解析 Serde 序列化框架:核心设计与 farm 仓库的 crates.io 补丁兼容方案

深入解析 Serde 序列化框架:核心设计与 farm 仓库的 crates.io 补丁兼容方案

前端构建构建工具开发工具 【免费下载链接】farm Extremely fast Vite-compatible web build tool written in Rust 项目地址: https://gitcode.com/gh_mirrors/fa/farm 点击查看 免费下载 本篇文章以本仓库 patches/serde/crates-io.md(Serde 发布到 c…

2026/10/13 7:58:24 阅读更多 →
Lambda架构性能测试实战:批处理、实时链路与服务层的压测方法

Lambda架构性能测试实战:批处理、实时链路与服务层的压测方法

1. 为什么Lambda架构需要一套独立的性能测试方法做大数据系统的人,对Lambda架构应该都不陌生——批处理层负责全量数据的离线计算,速度层负责实时数据的增量计算,服务层再把两层结果合并起来对外提供统一查询。这套架构把“准确”和“低延迟”…

2026/10/13 7:58:24 阅读更多 →
手把手教你实现自己的“Manus”:基于容器隔离的多用户Agent应用搭建指南

手把手教你实现自己的“Manus”:基于容器隔离的多用户Agent应用搭建指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 7:58:24 阅读更多 →
Litellm:大模型调用的统一抽象层与生产级路由网关

Litellm:大模型调用的统一抽象层与生产级路由网关

1. 为什么“litellm”突然在开发者圈里刷屏?它到底不是个新模型,而是一把万能钥匙最近两周,好几个不同技术栈的同行在群里发截图:有人在用 Python 调通了本地运行的 Qwen3,有人把公司私有部署的 DeepSeek-R1 接进了旧版…

2026/10/13 7:57:23 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 21:05:09 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →