LangChat 代码执行引擎 (Sandbox) 设计文档
一、模块定位
Sandbox 模块为 LangChat 平台提供安全的代码执行能力,支持在工作流节点中运行用户编写的 JavaScript、Python 和 Shell 代码。模块位于langchat-core 的 cn.langchat.core.sandbox 包中,作为核心基础能力供上层业务(如工作流引擎)调用。
限制
GraalPy 本质上是一个嵌入在 JVM 中的 Python 解释器,它只包含 Python 标准库(json、math、re、datetime、collections 等)。它没有 pip,也无法自动下载安装第三方包。 更关键的限制是:即使手动放入 numpy,它也跑不起来,因为 numpy 依赖 C/Fortran 编译的原生扩展(BLAS/LAPACK),而 GraalPy 运行在 JVM 之上,无法加载 .so/.dylib 原生库。 总结一下各类 Python 库的支持情况:| 分类 | 示例 | GraalPy 支持 | 原因 |
|---|---|---|---|
| 标准库 | json, math, re, datetime, collections | 支持 | 纯 Python 实现,内置 |
| 纯 Python 第三方库 | pyyaml, jinja2 | 理论可行 | 需手动放入,无 C 扩展依赖 |
| C 扩展第三方库 | numpy, pandas, scipy, pillow | 不支持 | 依赖原生 C 编译,JVM 无法加载 |
| 网络请求库 | requests, httpx | 不支持 | 沙箱限制 + 依赖链复杂 |
二、架构设计
2.1 Provider 模式
采用 Provider(供应商)模式,将代码执行的调度层和执行层解耦:2.2 目录结构
2.3 核心接口
2.4 使用示例
三、执行器详解
3.1 GraalVM Polyglot 执行器
| 属性 | 说明 |
|---|---|
| 支持语言 | JavaScript (GraalJS)、Python (GraalPy) |
| 隔离级别 | GraalVM 沙箱隔离(无法访问宿主文件系统和网络) |
| 代码规范 | 必须包含 main(params) 函数作为入口 |
| 超时控制 | 默认 30 秒,可自定义 |
| 代码限制 | 最大 100,000 字符 |
3.2 本地命令行执行器
| 属性 | 说明 |
|---|---|
| 支持语言 | Shell (bash/sh) |
| 隔离级别 | 无隔离,直接在宿主操作系统上执行 |
| 代码规范 | 标准 Shell 命令/脚本,无 main 函数要求 |
| 代码限制 | 最大 50,000 字符 |
3.3 远程 Sandbox 执行器(预留)
| 属性 | 说明 |
|---|---|
| 支持语言 | 由远程服务决定(理论上支持所有语言) |
| 隔离级别 | Docker 容器级隔离 |
| 扩展能力 | 支持安装第三方库(numpy、pandas 等) |
| 部署方式 | 独立 Sandbox 服务,通过 HTTP API 调用 |
四、核心依赖
4.1 GraalVM Polyglot 引擎
org.graalvm.polyglot.Context 创建沙箱化的执行环境。
核心类:
GraalVmJavaScriptExecutionEngine— 创建 GraalJS 上下文执行 JavaScriptGraalVmPythonExecutionEngine— 创建 GraalPy 上下文执行 Python
4.2 本地命令行引擎
CommandLineExecutionEngine— 通过ProcessBuilder在本地执行 Shell 命令
五、Python 类库支持与限制
5.1 GraalPy 支持的标准库
| 模块 | 说明 | 示例 |
|---|---|---|
json | JSON 序列化/反序列化 | json.loads(), json.dumps() |
math | 数学函数 | math.sqrt(), math.pi, math.factorial() |
re | 正则表达式 | re.findall(), re.sub() |
datetime | 日期时间处理 | datetime.now(), timedelta() |
collections | 集合工具 | Counter, defaultdict, OrderedDict |
itertools | 迭代器工具 | chain(), combinations() |
functools | 函数工具 | reduce(), partial() |
string | 字符串常量 | string.ascii_letters, Template |
random | 随机数 | random.randint(), random.choice() |
hashlib | 哈希算法 | hashlib.md5(), hashlib.sha256() |
5.2 不支持的第三方库
GraalPy 运行在 JVM 之上,不支持需要 C 扩展编译的第三方库:| 库 | 原因 |
|---|---|
| numpy | 依赖 C/Fortran 扩展 (BLAS/LAPACK) |
| pandas | 依赖 numpy + C 扩展 |
| requests | 依赖 urllib3 + C SSL 绑定 |
| scipy | 依赖 numpy + C/Fortran 扩展 |
| matplotlib | 依赖 C 扩展渲染引擎 |
| pillow (PIL) | 依赖 C 图像处理库 |
RemoteCodeExecutor 调用独立部署的 Sandbox 服务,在真实的 Python 环境中执行。
六、错误处理
6.1 结构化异常
CodeExecutionException 包含 ErrorType 枚举,分类所有可能的错误:
| ErrorType | 触发场景 |
|---|---|
EMPTY_CODE | 代码为空 |
INVALID_FORMAT | 代码缺少 main 函数 / 超出长度限制 |
TIMEOUT | 执行超时(死循环、大量计算) |
RUNTIME_ERROR | 语法错误、类型错误、引用错误、除零错误等 |
ENGINE_INIT_FAILED | GraalVM 引擎初始化失败 |
UNKNOWN | 未分类的错误 |
6.2 错误信息提取
GraalVM 的原始异常信息通常很长且包含堆栈跟踪。GraalVmCodeExecutor 内部会解析常见错误类型(SyntaxError、TypeError、NameError、ImportError 等),提取用户友好的错误摘要。
七、已知限制与弊端
7.1 GraalVM 引擎限制
| 限制 | 影响 | 规避方式 |
|---|---|---|
| 不支持 C 扩展 Python 库 | 无法使用 numpy/pandas 等数据科学库 | 使用远程 Sandbox |
| 首次执行冷启动慢 | 第一次创建 Context 需要 1-3 秒 | 引擎预热 / 复用 Context |
| 内存占用较大 | 每个 GraalVM Context 占用 50-100MB | 控制并发数 |
| Python 兼容性非 100% | 部分 Python 3 语法/特性可能不支持 | 提前测试验证 |
7.2 本地命令行限制
| 限制 | 影响 | 规避方式 |
|---|---|---|
| 无沙箱隔离 | 可执行任意系统命令(rm -rf 等) | 调用方做命令白名单过滤 |
| 平台依赖 | Shell 语法在 Windows/Linux/macOS 上可能不同 | 明确目标运行平台 |
| 无超时控制 | CommandLineExecutionEngine 本身不支持超时 | 上层做超时控制 |
7.3 架构层面
| 限制 | 说明 |
|---|---|
| 每次创建新引擎实例 | 当前每次执行都 new 一个 Engine,无法复用,影响性能 |
| 无资源计量 | 无法限制 CPU/内存使用量,恶意代码可能耗尽资源 |
| 无多租户隔离 | 所有用户共享同一个执行环境 |
八、网络请求能力说明
8.1 各执行器的网络能力对比
| 执行器 | 网络请求能力 | 原因 | 替代方案 |
|---|---|---|---|
| GraalVM JS | 不支持 | 沙箱中无 fetch/XMLHttpRequest/WebSocket API | 使用 Shell curl |
| GraalVM Python | 不支持 | requests/urllib/socket 等模块不可用(C 扩展 + 沙箱限制) | 使用 Shell curl |
| Local Shell | 完全支持 | 直接在宿主机执行 curl/wget 等命令 | — |
| Remote Sandbox | 取决于远端 | 远端容器可安装任意依赖 | — |
8.2 Shell 网络请求示例
8.3 JS/Python 中处理网络数据的推荐模式
由于 JS/Python 沙箱无法直接发起网络请求,推荐采用两阶段模式:- 阶段一:由外部(Shell
curl或 JavaHttpClient)完成 HTTP 调用,获取响应 JSON - 阶段二:将响应 JSON 作为参数传入 JS/Python 沙箱,由沙箱负责数据解析和转换
九、Shell 系统信息获取能力
Shell 执行器可以获取宿主机的各类系统信息,常用命令如下:9.1 磁盘与目录
| 功能 | 命令 | 说明 |
|---|---|---|
| 磁盘使用概览 | df -h | 显示所有挂载点的磁盘使用情况 |
| 根目录列表 | ls -la / | 列出根目录下所有文件和目录 |
| 用户主目录 | ls -la $HOME | 列出当前用户主目录内容 |
| 当前工作目录 | pwd | 输出当前工作路径 |
| 目录大小 | du -sh /* | sort -rh | head -10 | 按大小排序显示各目录 |
| 查找大文件 | find . -type f -size +1M | head -10 | 查找超过 1MB 的文件 |
9.2 网络与 IP
| 功能 | 命令 | 兼容性 |
|---|---|---|
| 本机 IP (macOS) | ifconfig | grep 'inet ' | grep -v '127.0.0.1' | awk '{print $2}' | macOS |
| 本机 IP (Linux) | ip -4 addr show | grep -oP 'inet \K[\d.]+' | grep -v '127.0.0.1' | Linux |
| 公网 IP | curl -s https://httpbin.org/ip | 需要网络 |
| 主机名 | hostname | 通用 |
| 网络接口列表 | ifconfig -l (macOS) 或 ip link show (Linux) | 平台相关 |
| 端口监听 | lsof -iTCP -sTCP:LISTEN -P -n (macOS) 或 ss -tlnp (Linux) | 平台相关 |
| DNS 查询 | nslookup baidu.com 或 dig +short baidu.com | 需安装工具 |
9.3 主机与运行环境
| 功能 | 命令 |
|---|---|
| 系统信息 | uname -a |
| 当前用户 | whoami |
| 用户详情 | id |
| 环境变量 | env |
| CPU 信息 (macOS) | sysctl -n machdep.cpu.brand_string |
| CPU 核数 (macOS) | sysctl -n hw.ncpu |
| 内存总量 (macOS) | sysctl -n hw.memsize |
| CPU 信息 (Linux) | cat /proc/cpuinfo |
| 内存信息 (Linux) | free -h 或 cat /proc/meminfo |
| 系统运行时间 | uptime |
| 进程列表 | ps aux | sort -k3 -rn | head -10 |
十、扩展路线
- 引擎复用池:复用 GraalVM Context,减少冷启动时间
- 远程 Sandbox 实现:对接 Docker 容器化的代码执行服务,支持完整的 Python 生态
- 资源限制:通过 GraalVM ResourceLimits API 限制 CPU 和内存
- 执行审计:记录每次代码执行的输入、输出、耗时,便于安全审计
- 命令白名单:为 Shell 执行器增加命令过滤机制

