celld Worker Loader实验特性实战:在Worker内动态启动沙箱isolate
【免费下载链接】celldself-hosted, distributed Durable Objects项目地址: https://gitcode.com/GitHub_Trending/ce/celld
celld 是一个自托管、分布式的 Durable Objects 运行时,让你在自己的机器上运行 Cloudflare Workers 和 Durable Objects。本文介绍它的实验特性Worker Loader(Code Mode):允许一个正在运行的 Worker 在运行时接收代码,动态启动一个沙箱 isolate并调用它。整个过程无需重启、无需重新部署,是 celld 对标 Cloudflare Worker Loader 的移植实现。
一、什么是 Worker Loader:Worker 里的"Worker 生成器"
传统 Workers 的部署产物是静态的,代码上线后不再变化。Worker Loader 解锁的是"运行时写代码、运行时执行"的能力:
- 调用方把一段代码(JSON 描述 + 源码)交给
loader - celld 在后台线程池里把它编译成一个全新的 V8 isolate
- 这个沙箱与调用方的 isolate 内存隔离,互不干扰
- 调用方通过
fetch()或 JS RPC 与它通信
核心实现在 crates/celld/js.rs,注释里写得很直白:动态 worker 复用与无状态 Worker 相同的 turn 驱动,等待期间不占用线程,所以沙箱"几乎免费"。
二、一行环境变量开启:CELLD_WORKER_LOADER
该特性默认关闭(属于实验特性),启动节点时设置环境变量即可开启:
CELLD_WORKER_LOADER=LOADER \ celld --bucket s3://my-cells-bucket \ --listen 0.0.0.0:8080 \ --internal-listen 10.0.0.12:8081 \ --advertise 10.0.0.12:8081值LOADER是绑定名,设置后每个 Worker 的env里都会多出一个env.LOADER。CLI 帮助中它被明确标注在 EXPERIMENTAL 分组,见 crates/celld/main/cli.rs。启动时绑定如何注入,可看 crates/celld/js/bootstrap.rs。
三、两个入口 API:load() 与 get()
JS 侧的 loader 对象由 crates/celld/js/harness.js 生成,提供两个入口:
| API | 行为 | 生命周期 |
|---|---|---|
loader.load(code) | 加载一个匿名worker | 最后一个 stub 被 GC 时自动回收 isolate,不泄漏 |
loader.get(name, getCode) | 按名字记忆化加载 | 同名复用同一个 isolate,长期存活 |
getCode可以是异步函数:加载被延迟到 microtask,错误会在使用 worker 时以 reject 形式暴露,而不是在get()/load()时抛出。
拿到 stub 后,还有两个常用方法:
getEntrypoint(name):获取入口点,默认"default"dispose():显式销毁;也支持Symbol.dispose,可以配合using声明式释放
一个最小示例(动态加载一段代码并调它的 RPC 方法):
export default { async fetch(request, env) { const stub = env.LOADER.load({ mainModule: "main", modules: { main: "export const ping = () => 'pong'" }, }); const ep = stub.getEntrypoint(); return Response.json(await ep.ping()); }, };四、如何调用沙箱:fetch() 与单方法 RPC
每个 loaded worker 的入口点暴露两种调用方式:
fetch(input, init):标准的 HTTP 调用,返回带 status、headers 和 body 的 Response- 单方法 RPC 调用:
ep.ping()这类一次性的方法调用,走结构化克隆传参和返回值
目前尚未支持的能力(会明确报错,而不是静默降级):
- awaitable 属性(
get形式的 RPC 属性) - pipelined 属性路径(
ep.a.b()这种多级链路) globalOutbound作为 Fetcher 代理(只实现了null= 完全禁止出站和缺省 = 继承调用方权限)
五、资源限制:与 workerd 完全对齐
celld 镜像了 Cloudflare workerd 的动态 worker 限制,常量定义在 crates/celld/js.rs:
| 限制项 | 数值 | 说明 |
|---|---|---|
| 代码总大小 | 64 MiB | 超限直接拒绝,连解析都不会发生 |
| env 大小 | 1 MiB | 只接受 plain-JSON 值 |
| 并发 loaded worker 数 | 默认 256 | 用CELLD_MAX_LOADED_WORKERS调整 |
其中并发上限的意义在源码注释里写得很清楚:防止失控的 agent 循环把 isolate 耗尽。超限调用会抛出worker loader: too many loaded workers (limit ...)。
另外,传入globalOutbound: null可以给沙箱断网,让它成为真正的"纯计算沙箱"——这是安全场景下值得优先采用的写法。
六、适合什么场景
- AI 代码解释器:大模型生成的代码放进沙箱执行,隔离 + 可断网 + 可限额
- 插件系统:用户自定义插件运行时加载,互不影响
- 动态策略引擎:规则代码热更新,无需重新部署整个 Worker
配合 celld 每个 cell 自带 SQLite、节点可整体替换的架构,沙箱化执行 + 持久状态可以组合出相当多的应用形态。
七、源码与文档索引
| 资料 | 路径 |
|---|---|
| 特性总览与 API 说明 | docs/cloudflare-compat.md |
| 环境变量表(CELLD_WORKER_LOADER / CELLD_MAX_LOADED_WORKERS) | docs/README.md |
| Rust 侧 op 实现(加载/调用/RPC/回收) | crates/celld/js.rs |
| JS 侧 loader 构造 | crates/celld/js/harness.js |
| 多模块(sibling modules)注册 | crates/celld/js/modules.rs |
八、注意事项 ⚠️
- 实验特性:API 可能在后续版本变化,生产环境请做好版本固定
- stub 不能跨 isolate 传递:与 celld 其他 isolate 间 RPC 的限制一致,参数和返回值必须可结构化克隆
- 能力型绑定(capability stubs)尚未支持:
env只能传 plain-JSON 值 - 匿名
load()依赖 GC 回收,若需要确定性释放,请显式调用dispose()
Worker Loader 让 celld 从"运行静态 Worker"进阶到"运行时生成 Worker",是自托管 Durable Objects 平台上非常有想象力的一块拼图。先拿它跑一个断网的代码沙箱,是上手最快的方式。
【免费下载链接】celldself-hosted, distributed Durable Objects项目地址: https://gitcode.com/GitHub_Trending/ce/celld
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考