如何基于Jupyter内核自研NoteBook

简介

自研NoteBook如何高效地管理 Jupyter Kernel 的生命周期、处理代码执行请求,以及实现实时的消息推送,是其中的核心。本文将分享一套基于微服务架构的 Jupyter 内核管理系统的设计思路和实现方案。

租户Jupyter服务管理

1.使用miniforge管理python的依赖包

2.每个租户单独启动一个pod启动对应的jupyter服务,启动命令如下

bash 复制代码
/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  --port=8888 --NotebookApp.base_url="/web/${IDE_CR_NAME}/jupyter" --NotebookApp.disable_check_xsrf=True

整体架构

系统采用微服务架构,将功能拆分为多个独立的服务模块,各司其职,

核心组件职责

    • **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`: 已停止或崩溃

**示例场景**:

bash 复制代码
```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 1

import pandas as pd

df = pd.DataFrame({'A': [1, 2, 3]})

Cell 2 (可以访问 Cell 1 中定义的变量)

print(df.head()) # 输出 DataFrame 的前几行

内核创建流程详解

完整请求流程

关键设计点

内核创建接口

**接口设计**:

bash 复制代码
```http POST /api/kernel/bind

Content-Type: application/json

{

"kernelName": "python3",

"notebookId": "notebook-uuid"

}

```

**响应示例**:

bash 复制代码
```json

{

"code": 0,

"data": {

"kernelId": "kernel-uuid",

"status": "idle"

}

}

```

2.2.2 内核规格查询

系统支持查询可用的内核类型,前端可以根据此信息展示内核选择界面

bash 复制代码
```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 Session

private static final Map<String, 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 的连接:

java 复制代码
@Service

public class WebSocketPool {

// 内核ID -> WebSocket连接的映射

private final static Map<String, 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

  1. | `/api/kernel/specs` | GET | 获取可用内核列表 |
  2. | `/api/kernel/list` | GET | 获取运行中的内核列表 |
  3. | `/api/kernel/bind` | POST | 创建并绑定内核到 Notebook |
  4. | `/api/kernel/delete` | DELETE | 删除内核 |

代码执行 API

  1. | `/api/cell/add` | POST | 添加新的代码单元 |
  2. | `/api/cell/save` | POST | 保存代码单元内容 |
  3. | `/api/cell/run` | POST | 执行代码单元 |
  4. | `/api/cell/result` | GET | 获取执行结果 |

Gateway 层 API

  1. | `/api/gateway/kernel/create` | POST | 创建内核实例 |
  2. | `/api/gateway/kernel/connect` | POST | 建立 WebSocket 连接 |
  3. | `/api/gateway/message/send` | POST | 发送代码执行请求 |
  4. | `/api/gateway/kernel/status` | GET | 检查内核状态 |

连接池管理

Gateway 层维护 WebSocket 连接池,避免重复创建连接:

java 复制代码
```java

// 获取连接,如果不存在则创建

WebSocketConnection connection = pool.getConnection(kernelId);

if (connection == null) {

connection = new WebSocketConnection(kernelId, endpoint);

pool.addConnection(kernelId, connection);

}

```

数据模型设计

7.1 核心数据表

内核信息表 (kernel_info)

| 字段 | 类型 | 说明 |

|-----|------|------|

| id | BIGINT | 主键 |

| kernel_id | VARCHAR | 内核ID (Jupyter生成) |

| kernel_name | VARCHAR | 内核名称 |

| kernel_status | VARCHAR | 内核状态 |

| gateway_host | VARCHAR | Gateway 主机地址 |

| manager | VARCHAR | 管理者用户ID |

| kernel_endpoint | VARCHAR | Jupyter Server 地址 |

相关推荐
W如Q扬2 小时前
python程序使用supervisor启停
python·supervisor
Piar1231sdafa2 小时前
蓝莓果实检测与识别——基于decoupled-solo_r50_fpn_1x_coco模型实现
python
拾零吖2 小时前
Python 常用内置函数
python
行走的bug...2 小时前
python项目管理
开发语言·python
其美杰布-富贵-李2 小时前
tsai 完整训练流程实践指南
python·深度学习·时序学习·fastai
m0_462605222 小时前
第N9周:seq2seq翻译实战-Pytorch复现-小白版
人工智能·pytorch·python
纪伊路上盛名在2 小时前
记1次BioPython Entrez模块Elink的debug
前端·数据库·python·debug·工具开发
CryptoRzz2 小时前
日本股票 API 对接实战指南(实时行情与 IPO 专题)
java·开发语言·python·区块链·maven
ss2732 小时前
考研加油上岸祝福弹窗程序
python