第 15 章 · 部署:Node.js 与 Cloudflare Workers
本章目标:把 Flue agent 部署到两大官方目标——Node.js 长驻服务与 Cloudflare Workers 边缘运行时,理解各自的持久化与密钥管理差异。
15.1 部署目标的共同前提
无论部署到哪里,都要先解决三件事:
text
① 构建产物(@flue/vite 负责打包 agent 代码)
② Provider 密钥注入(环境变量 / Secrets)
③ 持久化存储(Durability 状态放哪)typescript
// vite.config.ts — 两种目标的构建配置入口
import { flue } from '@flue/vite';
import { defineConfig } from 'vite';
export default defineConfig({
plugins: [flue()], // 处理 'use agent' 指令与运行时打包
});15.2 Node.js 部署
Node 是最直接的长期运行目标:进程常驻,恢复在启动时自动进行。
typescript
// src/main.ts — 生产入口
import { createApp } from '@flue/runtime/node';
import { postgresAdapter } from '@flue/postgres';
import { Pool } from 'pg';
const app = createApp({
// 生产必须外接持久化,进程重启才能恢复受理中的会话
database: postgresAdapter({
pool: new Pool({ connectionString: process.env.DATABASE_URL }),
}),
});
app.listen(process.env.PORT ?? 3000);bash
# 构建并运行
npm run build # vite build
NODE_ENV=production node dist/main.js
# 用 PM2 守护(或 systemd / Docker)
pm2 start dist/main.js --name flue-botdockerfile
# Dockerfile — 容器化 Node 部署
FROM node:22-slim
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY dist ./dist
# 密钥通过环境变量注入,绝不写进镜像
ENV NODE_ENV=production
CMD ["node", "dist/main.js"]15.3 Cloudflare Workers 部署
Workers 是无服务器 isolate:没有常驻进程,靠请求与闹钟唤醒,持久化天然走数据库。
typescript
// src/worker.ts — Workers 入口
import { createWorkerApp } from '@flue/runtime/cloudflare';
export default {
async fetch(request: Request, env: Env): Promise<Response> {
// env 中拿到绑定:数据库(D1/Hyperdrive)与 Secrets
const app = createWorkerApp({ env });
return app.fetch(request);
},
// cron 闹钟:定期推进未完结的受理(见第 12 章恢复行为)
async scheduled(_ctrl: ScheduledController, env: Env) {
const app = createWorkerApp({ env });
await app.resumePending();
},
};toml
# wrangler.toml — Workers 配置
name = "flue-agent"
main = "src/worker.ts"
compatibility_date = "2026-01-01"
[triggers]
crons = ["*/5 * * * *"] # 每 5 分钟唤醒一次做恢复检查bash
npx wrangler deploy15.4 密钥与环境变量
两个目标的注入机制不同,但读取方式统一:
| 目标 | 本地开发 | 生产注入 |
|---|---|---|
| Node.js | .env 文件 | 系统环境变量 / Docker ENV / K8s Secret |
| Workers | .dev.vars 文件 | wrangler secret put XXX |
bash
# Workers 密钥注入(交互式,不落盘)
npx wrangler secret put ANTHROPIC_API_KEY
npx wrangler secret put DATABASE_URLtypescript
// 统一读取:代码不感知部署目标差异
// Node: process.env.XXX;Workers: env.XXX(由适配器归一化)
const apiKey = env.ANTHROPIC_API_KEY ?? process.env.ANTHROPIC_API_KEY;
if (!apiKey) throw new Error('missing ANTHROPIC_API_KEY');两个目标的本质差异
Node:进程常驻 → 崩溃后由重启触发恢复;Workers:isolate 随时回收 → 由下一次请求或 cron 触发恢复。业务代码几乎不变,但运维心智不同。
15.5 本章小结
- 共同前提:
@flue/vite构建、密钥注入、外接持久化; - Node 长驻:
postgresAdapter+ PM2/Docker 守护,重启即恢复; - Workers 无服务器:
createWorkerApp({ env })+ cron 闹钟做恢复检查; - 密钥本地用
.env/.dev.vars,生产用系统环境变量或wrangler secret put。
🧪 随堂测验
点击你认为正确的选项。答错时会展示正确答案与原因解析。
1. Node.js 与 Cloudflare Workers 部署 Flue 时,恢复(recovery)的触发方式有何不同?
2. 在 Cloudflare Workers 上管理生产密钥的正确方式是?
3. 为什么 Workers 部署通常要配置 cron trigger?
4. 关于 @flue/vite 在部署中的作用,正确的说法是?
🛠️ 动手实践
- 把第 11 章的 Triage agent 部署为 Node 服务,用 PM2 守护并验证 kill 后自动拉起。
- 部署同一 agent 到 Cloudflare Workers,配置 5 分钟 cron,在 Dashboard 观察唤醒日志。
- 分别用
.env与wrangler secret put注入密钥,写一份团队密钥管理清单。