news 2026/10/28 23:11:40

基于 Cloudflare Workers 构建边缘 AI Agent 运行环境:cloudflare-os 设计思路与实操

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于 Cloudflare Workers 构建边缘 AI Agent 运行环境:cloudflare-os 设计思路与实操

1. 从标题到落地:cloudflare-os 到底在折腾什么

第一次看到cloudflare-os这个标题,我脑子里蹦出来的不是某个具体的操作系统镜像,而是一整套围绕 Cloudflare Workers 构建的“类操作系统”思路。它不是一个能装进硬盘、开机进 BIOS 的系统,而是一个把边缘计算节点当作“硬件”、把 Workers 当作“进程”、把各类 API 和存储服务当作“外设”的抽象层。说白了,就是用 Serverless 的方式,在 Cloudflare 的全球网络上搭出一个能跑 AI Agent、能调度任务、能持久化状态的轻量级运行环境。

这个项目解决的核心问题很实际:当你手头有一堆 AI 能力——比如大模型推理、语音合成、图像生成——却不想维护一台常年开机的服务器,也不想被某一家云厂商的虚拟机绑死,那 Cloudflare Workers 加上它的生态(KV、D1、R2、Queues、Durable Objects)就是一个很顺手的底座。cloudflare-os这个标题背后,大概率是在探索如何把这些零散的服务组合成一个有“系统感”的东西:有调度、有状态、有对外接口、有内部通信。

适合谁来参考?如果你已经写过几个 Workers,对wrangler这个 CLI 不陌生,并且想进一步把 AI Agent 或者多步骤任务流部署到边缘节点上,那这篇内容就是给你准备的。如果你只是听说过 Cloudflare 但没动过手,也没关系,我会把关键概念用生活化的方式拆开讲,保证你能跟上节奏。整个思路的核心关键词就几个:Cloudflare Workers、AI、pnpm、wrangler,以及围绕它们衍生出来的工程实践。

我自己的习惯是,拿到一个类似cloudflare-os这样的概念,先不急着写代码,而是画一张“资源地图”:哪些东西是计算、哪些是存储、哪些是通信、哪些是调度。这张图画清楚了,后面选型、写配置、排查问题都会顺很多。下面我就按这个逻辑,把整个项目的设计思路、核心细节、实操过程和踩坑经验一层层展开。

2. 整体设计与思路拆解:为什么是 Workers 而不是一台 VPS

2.1 边缘计算作为“硬件层”的合理性

传统做法里,你要跑一个 AI Agent,第一反应是买一台 VPS,装好 Node.js,用pnpm装依赖,然后pm2或者systemd把进程守护起来。这套流程我闭着眼睛都能走完,但它有几个绕不开的痛点:第一,你得选机房,选完发现用户分布在各地,延迟参差不齐;第二,你得处理操作系统更新、安全补丁、磁盘满了、内存泄漏;第三,流量一上来,单机扛不住,你得手动扩容,扩完还要考虑负载均衡。

Cloudflare Workers 的思路是把这些脏活累活全部收走。你写一个函数,部署上去,它自动在全球几百个节点运行。用户请求进来,就近执行。没有操作系统要维护,没有进程要守护,没有磁盘要清理。对于cloudflare-os这种定位的项目来说,这相当于把“硬件层”抽象掉了,你只需要关心“系统调用”怎么写。

但这里有个关键取舍:Workers 的运行环境不是完整的 Node.js。它基于 V8 隔离区,支持 Web 标准 API(Fetch、Request、Response、Streams、Crypto),但 Node.js 的很多内置模块(比如fs、net、child_process)是用不了的。这意味着你不能直接把一个现成的 Node 项目扔上去就跑。cloudflare-os如果要做成一个“系统”,就必须在这个约束下重新设计它的“系统调用接口”。

我的判断是,这个项目选择 Workers 作为底座,核心动机有三个:全球低延迟、免运维、按需付费。尤其是当你的 AI Agent 需要频繁调用外部 API 时,边缘节点的网络出口往往比一台位于某个固定区域的 VPS 更稳定,因为它会自动选择最优路径。

2.2 存储层的选型逻辑:KV、D1、R2 各管什么

一个“操作系统”不能没有存储。Cloudflare 提供了几种存储原语,每种都有明确的适用场景,选错了后面会很痛苦。

KV(Key-Value)适合读多写少、对一致性要求不高的场景。比如缓存 AI 模型的元数据、存储用户配置、记录简单的会话状态。它的读取速度极快,因为数据会被复制到边缘节点,但写入有延迟,而且不保证强一致。我一般用它来存“丢了也能重建”的数据。

D1是 SQLite 的托管版本,适合需要关系查询的场景。比如你要记录每个 AI 任务的执行日志、统计 token 消耗、管理用户和权限的关系。它的优势是支持 SQL,上手快,但写入性能有限,不适合高并发写入。如果你的cloudflare-os需要维护一张任务表,D1 是合理的选择。

R2是对象存储,兼容 S3 API,但没有出口流量费。适合存大文件:AI 生成的图片、音频、视频,或者模型权重文件。它的读取需要通过 Workers 绑定或者预签名 URL,不能像本地文件系统那样直接open。

Durable Objects是一个比较特殊的存在,它提供了强一致的单一实例,可以用来做协调、锁、实时通信。如果你的“操作系统”需要有一个全局的调度器,或者需要维护 WebSocket 连接的状态,Durable Objects 就是那个“内核态”的组件。

我在实际项目里的经验是:不要试图用一种存储解决所有问题。KV 做缓存,D1 做结构化数据,R2 做大文件,Durable Objects 做协调,各司其职。cloudflare-os如果设计得合理,应该也是这个组合。

2.3 包管理与构建工具:pnpm 和 wrangler 的分工

pnpm和wrangler这两个词在热词里反复出现,说明很多人在这个环节卡住了。我先说清楚它们各自干什么。

pnpm是包管理器,负责把你的项目依赖装到node_modules里。它比 npm 快,磁盘占用小,因为用了硬链接和内容寻址存储。wrangler是 Cloudflare 官方的 CLI,负责本地开发、构建、部署 Workers。它俩的关系是:pnpm管依赖,wrangler管部署。

但这里有个常见的坑:wrangler本身也是一个 npm 包,你可以用pnpm装它,也可以用 npm 装。热词里出现“pnpm 不是内部或外部命令”和“pnpm 无法将 pnpm 项识别为 cmdlet”,说明很多人在 Windows 上装完 pnpm 之后,命令行找不到它。这通常是因为 pnpm 的全局 bin 目录没有加到 PATH 里。解决办法后面会详细讲。

另一个热词是“pnpm 离线安装”和“pnpm 离线安装包”。这说明有些人的网络环境不稳定,或者在公司内网里没法直接访问 npm registry。pnpm 支持通过--offline参数使用本地缓存,也支持配置私有 registry。如果你在受限网络里做cloudflare-os,提前把依赖缓存好是关键。

至于“删除 pnpm”这个热词,我猜是有人装错了版本或者装坏了想重来。pnpm 的卸载在不同系统上方法不同,Windows 上用 npm 卸载,macOS 上用 brew 或者 npm,Linux 上取决于你怎么装的。这个后面也会给具体命令。

3. 核心细节解析与实操要点:从零搭起一个可跑的骨架

3.1 环境准备:pnpm 和 wrangler 的正确安装姿势

先说pnpm的安装。官方推荐的方式是用 corepack,这是 Node.js 自带的工具,能帮你管理包管理器的版本。如果你用的是 Node 16.13 以上,直接运行:

corepack enable corepack prepare pnpm@latest --activate

这样装出来的 pnpm 会跟着 Node 的版本走,不容易出 PATH 问题。如果你用 npm 全局装:

npm install -g pnpm

装完之后一定要验证:

pnpm -v

如果提示“不是内部或外部命令”,说明全局 bin 目录不在 PATH 里。Windows 上可以用npm config get prefix找到 npm 的全局目录,然后把这个目录加到系统环境变量 Path 里。macOS 和 Linux 上通常是/usr/local/bin或者~/.local/share/pnpm,检查一下 shell 配置文件(.bashrc、.zshrc)里有没有对应的 export。

wrangler的安装有两种方式。一种是全局装:

pnpm add -g wrangler

另一种是作为项目依赖装:

pnpm add -D wrangler

我更推荐第二种,因为不同项目可能依赖不同版本的 wrangler,全局装容易冲突。装完之后用pnpm wrangler --version验证。

注意:如果你在 Windows 上同时装了多个 Node 版本,pnpm 的全局 bin 目录可能会跟着 Node 版本变。切换 Node 版本后如果 pnpm 找不到了,重新跑一次corepack enable通常能解决。

3.2 项目初始化:wrangler init 之后要改什么

用wrangler init可以生成一个 Workers 项目的骨架。命令是:

pnpm wrangler init cloudflare-os

它会问你几个问题:要不要用 TypeScript、要不要生成 Git 仓库、要不要部署。我一般选 TypeScript,因为 Workers 的类型定义很完善,写起来有提示,能少踩很多坑。

生成出来的目录结构大概是:

cloudflare-os/ ├── src/ │ └── index.ts ├── package.json ├── tsconfig.json └── wrangler.toml

wrangler.toml是核心配置文件,里面要填name、main、compatibility_date。compatibility_date很重要,它决定了 Workers 运行时用哪个版本的 API。我一般设成当前日期,比如2024-01-01,这样能用上最新的特性。

如果你要用 KV、D1、R2,需要在wrangler.toml里声明绑定。比如:

[[kv_namespaces]] binding = "OS_KV" id = "你的KV命名空间ID" [[d1_databases]] binding = "OS_DB" database_name = "cloudflare-os-db" database_id = "你的D1数据库ID" [[r2_buckets]] binding = "OS_BUCKET" bucket_name = "cloudflare-os-storage"

这些 ID 需要先在 Cloudflare 控制台或者用 wrangler 命令创建。比如创建 KV:

pnpm wrangler kv:namespace create "OS_KV"

命令会返回一个 ID,把它填到wrangler.toml里。

3.3 核心代码结构:把“系统调用”抽象成模块

cloudflare-os的核心在于怎么组织代码。我的做法是分成几个模块:

  • src/index.ts:入口,负责路由分发。
  • src/kernel/:核心调度逻辑,比如任务队列、状态机。
  • src/drivers/:对接外部服务的适配层,比如 AI 模型 API、存储 API。
  • src/lib/:工具函数,比如 ID 生成、时间格式化、错误处理。

入口文件用fetch事件监听:

export default { async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> { const url = new URL(request.url); if (url.pathname === '/health') { return new Response('ok'); } if (url.pathname.startsWith('/api/')) { return handleApi(request, env, ctx); } return new Response('Not Found', { status: 404 }); } };

Env类型需要自己定义,把wrangler.toml里的绑定都列进去:

interface Env { OS_KV: KVNamespace; OS_DB: D1Database; OS_BUCKET: R2Bucket; AI_API_KEY: string; }

这样 TypeScript 就能给你提示,不会出现env.OS_KV是 undefined 的情况。

提示:AI_API_KEY这种敏感信息不要写死在代码里,用wrangler secret put AI_API_KEY命令上传,它会加密存储,运行时通过env访问。

3.4 依赖管理:pnpm 的 lockfile 和离线策略

pnpm会生成pnpm-lock.yaml,这个文件必须提交到 Git。它记录了每个依赖的确切版本和完整性哈希,保证不同机器上装出来的依赖完全一致。如果你在 CI 里构建,用pnpm install --frozen-lockfile可以确保不会意外更新依赖。

离线安装的场景是这样的:你在有网的机器上跑一次pnpm install,pnpm 会把包缓存到本地(默认在~/.pnpm-store或者%LOCALAPPDATA%\pnpm\store)。然后把整个项目目录和缓存目录一起拷贝到离线机器上,运行:

pnpm install --offline

它会直接从缓存里找包,不访问网络。如果缓存里没有,就会报错。所以离线之前要确保所有依赖都已经缓存过。

另一个技巧是用pnpm fetch。这个命令只下载依赖到缓存,不安装到node_modules。你可以把缓存目录打包,在离线环境里解压后运行pnpm install --offline。

4. 实操过程与核心环节实现:让 AI Agent 在边缘跑起来

4.1 任务调度器的实现:用 Durable Objects 做协调

一个“操作系统”需要能调度任务。假设你要跑一个 AI Agent,它需要先调用大模型生成文本,再调用语音合成生成音频,最后把音频存到 R2。这三个步骤有依赖关系,不能并行。如果同时有多个用户请求,你需要一个队列来管理。

Durable Objects 适合做这个协调者。每个 Durable Object 是一个单实例,可以维护内存状态,支持 WebSocket。你可以创建一个TaskScheduler类:

export class TaskScheduler { state: DurableObjectState; tasks: Map<string, Task>; constructor(state: DurableObjectState) { this.state = state; this.tasks = new Map(); } async fetch(request: Request) { const url = new URL(request.url); if (url.pathname === '/enqueue') { const task = await request.json(); const id = crypto.randomUUID(); this.tasks.set(id, { ...task, status: 'pending' }); await this.state.storage.put(id, this.tasks.get(id)); return new Response(JSON.stringify({ id }), { status: 202 }); } if (url.pathname === '/status') { const id = url.searchParams.get('id'); const task = await this.state.storage.get(id); return new Response(JSON.stringify(task)); } return new Response('Not Found', { status: 404 }); } }

然后在wrangler.toml里声明:

[[durable_objects.bindings]] name = "TASK_SCHEDULER" class_name = "TaskScheduler" [[migrations]] tag = "v1" new_classes = ["TaskScheduler"]

在入口文件里,根据路径把请求转发给 Durable Object:

if (url.pathname.startsWith('/task/')) { const id = env.TASK_SCHEDULER.idFromName('global'); const stub = env.TASK_SCHEDULER.get(id); return stub.fetch(request); }

这样所有任务都经过同一个 Durable Object 实例,天然串行化,不会出现并发冲突。

4.2 AI 调用的封装:超时、重试和降级

调用外部 AI API 是cloudflare-os的核心动作。但外部 API 不稳定,可能超时、可能限流、可能返回错误。你需要封装一层。

我的做法是写一个callAI函数,带超时和重试:

async function callAI(prompt: string, env: Env, retries = 3): Promise<string> { const controller = new AbortController(); const timeout = setTimeout(() => controller.abort(), 10000); try { const response = await fetch('https://api.example.com/v1/generate', { method: 'POST', headers: { 'Authorization': `Bearer ${env.AI_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ prompt }), signal: controller.signal }); if (!response.ok) { throw new Error(`AI API error: ${response.status}`); } const data = await response.json(); return data.text; } catch (error) { if (retries > 0) { await new Promise(resolve => setTimeout(resolve, 1000)); return callAI(prompt, env, retries - 1); } throw error; } finally { clearTimeout(timeout); } }

这里有几个细节:AbortController用来控制超时,setTimeout在 Workers 里是可用的,但要注意 Workers 有 CPU 时间限制,免费版是 10ms,付费版是 50ms。不过等待网络请求的时间不算 CPU 时间,所以 10 秒的超时是没问题的。

重试之间加一个延迟,避免瞬间打爆对方 API。如果重试三次都失败,就抛错,让上层决定是返回错误还是降级到缓存。

注意:Workers 的fetch默认会跟随重定向,但有些 AI API 的重定向会丢失 POST body。如果遇到这种情况,设置redirect: 'manual'自己处理。

4.3 状态持久化:KV 和 D1 的配合使用

任务的状态需要持久化。我的做法是:热状态放 KV,冷数据放 D1。

热状态是指正在执行的任务的当前步骤、临时结果。这些数据读写频繁,但生命周期短。KV 的读取速度快,适合这种场景。比如:

await env.OS_KV.put(`task:${id}:status`, 'processing', { expirationTtl: 3600 });

expirationTtl设置 1 小时后自动过期,避免垃圾数据堆积。

冷数据是指已完成的任务记录、统计数据。这些数据需要长期保存,而且可能需要按条件查询。D1 适合这种场景:

await env.OS_DB.prepare( 'INSERT INTO tasks (id, status, created_at, result) VALUES (?, ?, ?, ?)' ).bind(id, 'completed', Date.now(), result).run();

D1 的写入是异步的,但run()会等待完成。如果你不关心结果,可以用ctx.waitUntil()把写入放到后台:

ctx.waitUntil( env.OS_DB.prepare('INSERT INTO tasks ...').bind(...).run() );

这样不会阻塞响应返回。

4.4 部署与验证:wrangler deploy 之后看什么

部署命令很简单:

pnpm wrangler deploy

它会打包代码,上传到 Cloudflare,然后返回一个 URL。第一次部署可能会问你要不要创建新的 Worker,选是就行。

部署完之后,先访问/health确认服务活着。然后发一个测试请求:

curl -X POST https://cloudflare-os.your-subdomain.workers.dev/task/enqueue \ -H "Content-Type: application/json" \ -d '{"type": "generate", "prompt": "hello"}'

如果返回{"id": "..."},说明调度器在工作。然后用返回的 ID 查状态:

curl "https://cloudflare-os.your-subdomain.workers.dev/task/status?id=..."

如果看到status: "pending"或者"processing",说明任务已经进入队列。

查看实时日志用:

pnpm wrangler tail

这个命令会流式输出 Workers 的 console.log,调试的时候非常有用。但要注意,生产环境的日志量可能很大,tail会一直刷,建议在调试时用,平时关掉。

5. 常见问题与排查技巧实录:那些热词背后的真实坑

5.1 pnpm 命令找不到:PATH 问题的三种解法

热词里“pnpm 不是内部或外部命令”和“pnpm 无法将 pnpm 项识别为 cmdlet”出现的频率极高,说明这是 Windows 用户的头号问题。根本原因是 pnpm 的可执行文件不在系统的 PATH 环境变量里。

解法一:用 corepack。前面说过,corepack enable会把 pnpm 的 shim 放到 Node 的安装目录下,而这个目录通常已经在 PATH 里。这是最省心的办法。

解法二:手动加 PATH。先找到 pnpm 的全局 bin 目录:

npm config get prefix

Windows 上通常是C:\Users\你的用户名\AppData\Roaming\npm。把这个路径加到系统环境变量的 Path 里,重启终端。

解法三:用 npx。如果你只是偶尔用一下,可以直接npx pnpm install,npx 会自动找到 pnpm 并执行。但这不是长久之计,因为每次都要下载。

提示:如果你用 PowerShell,改完 PATH 后要重启 PowerShell 才能生效。cmd 也一样。别问我怎么知道的,我在这上面浪费过半小时。

5.2 pnpm 安装失败:网络和 registry 的排查顺序

“pnpm 下载失败”通常有几个原因:网络不通、registry 配置错误、缓存损坏。

第一步,检查 registry:

pnpm config get registry

默认应该是https://registry.npmjs.org/。如果你在国内,可能需要换成镜像源。但注意,换源之后 lockfile 里的 integrity 哈希可能对不上,导致--frozen-lockfile失败。我的建议是:只在安装时临时换源,不要提交换源后的 lockfile。

第二步,清缓存:

pnpm store prune

这个命令会删除没有被任何项目引用的包,释放空间。如果缓存损坏,可以手动删除 store 目录,然后重新安装。

第三步,检查代理。如果你在公司内网,可能需要配置 HTTP 代理:

pnpm config set proxy http://proxy.example.com:8080 pnpm config set https-proxy http://proxy.example.com:8080

但注意,代理配置会写入全局配置文件,用完记得删掉,否则换网络后会连不上。

5.3 wrangler 部署报错:兼容性日期和 Node 版本

wrangler deploy报错最常见的原因是compatibility_date设得太早,导致某些 API 不可用。比如你想用crypto.randomUUID(),这个 API 在2022-01-01之后的兼容性日期才默认启用。如果你设的是2021-01-01,就会报crypto.randomUUID is not a function。

解决办法很简单:把compatibility_date改成当前日期,或者至少2023-01-01之后。

另一个原因是 Node 版本太低。wrangler要求 Node 16.17 以上,推荐 18 或 20。用node -v检查,如果太低就升级。

还有一个隐蔽的坑:wrangler.toml里的main字段指向的入口文件路径不对。比如你写的是src/index.ts,但实际文件在src/worker/index.ts,部署时会报模块找不到。检查路径,确保大小写一致,因为有些系统区分大小写。

5.4 AI 调用超时:Workers 的时间限制和对策

Workers 的免费版有 10ms CPU 时间限制,付费版是 50ms。但等待网络请求的时间不算 CPU 时间,所以调用 AI API 本身不会触发限制。真正会触发限制的是你在代码里做大量计算,比如解析大 JSON、加密解密、图像处理。

如果你确实需要做重计算,有几个对策:一是升级到付费版,CPU 时间限制放宽到 50ms;二是把重计算拆成多个 Worker,用 Queue 串联;三是用 WASM 把计算密集型任务编译成二进制,执行效率更高。

另一个超时问题是 AI API 本身响应慢。我遇到过某个模型 API 平均响应 8 秒,偶尔超过 30 秒。Workers 的 fetch 默认没有超时,但 Cloudflare 的边缘节点有 30 秒的请求超时。如果 AI API 超过 30 秒没返回,连接会被切断。解决办法是设置自己的超时,比如 25 秒,超时后返回一个“处理中”的状态,让客户端轮询。

5.5 常见问题速查表

问题现象可能原因排查方法解决方案
pnpm 命令找不到PATH 未配置where pnpm或which pnpm用 corepack 或手动加 PATH
pnpm 下载失败网络或 registry 问题pnpm config get registry换镜像源或配置代理
wrangler 部署报错兼容性日期太早检查wrangler.toml改成当前日期
AI 调用超时API 响应慢wrangler tail看日志设置超时和重试
KV 读取不到数据绑定名称不对检查wrangler.toml和env确保 binding 名称一致
D1 写入失败SQL 语法错误看错误信息用prepare和bind
R2 上传失败文件太大检查文件大小分片上传或压缩
Durable Object 不响应迁移未应用检查migrations重新部署

提示:wrangler tail是排查线上问题的利器,但它只能看到console.log和未捕获的异常。如果你用了try/catch把异常吞掉了,tail 里是看不到的。所以 catch 块里一定要console.error。

6. 扩展思路:cloudflare-os 还能怎么玩

6.1 多 AI 协作的编排模式

热词里“多 AI 协作”和“ai agent”出现得很频繁。cloudflare-os如果要做成一个 Agent 运行平台,多 AI 协作是绕不开的。我的思路是:把每个 AI 能力封装成一个“驱动”,用 Durable Object 做编排器,按照预定义的流程调用不同的驱动。

比如一个内容生成流程:先用文本模型生成大纲,再用文本模型扩写,然后用图像模型生成配图,最后用语音模型生成音频。每个步骤的输出作为下一个步骤的输入。编排器负责维护上下文,处理失败重试,记录每一步的耗时和 token 消耗。

这种模式的好处是每个驱动可以独立升级、独立限流。如果图像模型挂了,可以降级到缓存里的默认图,不影响整个流程。

6.2 用 Queue 做异步任务队列

Cloudflare Queues 是另一个有用的组件。它适合处理大量异步任务,比如批量生成内容、定时清理过期数据。你可以把任务丢进 Queue,然后由消费者 Worker 慢慢处理。

配置 Queue 需要在wrangler.toml里声明:

[[queues.producers]] queue = "task-queue" binding = "TASK_QUEUE" [[queues.consumers]] queue = "task-queue" max_batch_size = 10 max_batch_timeout = 30

生产者用env.TASK_QUEUE.send()发消息,消费者在queue事件里处理。Queue 的好处是自带重试和死信队列,不用自己实现。

6.3 监控和告警:用 Analytics Engine 看趋势

Workers 自带 Analytics Engine,可以记录自定义指标。比如你想知道每天调用了多少次 AI API,平均耗时多少,可以在代码里写:

env.ANALYTICS.writeDataPoint({ blobs: ['ai_call'], doubles: [duration], indexes: ['cloudflare-os'] });

然后在 Cloudflare 控制台里建图表,看趋势。如果某个指标异常,可以设置告警,通过邮件或者 Webhook 通知。

我自己的习惯是至少监控三个指标:请求量、错误率、AI 调用平均耗时。请求量突然下降可能是部署出了问题,错误率上升可能是某个依赖挂了,耗时上升可能是 AI API 变慢了。这三个指标能覆盖大部分异常情况。

6.4 本地开发:wrangler dev 的正确用法

wrangler dev可以在本地模拟 Workers 环境,支持热重载。但它默认是远程模式,会把请求转发到 Cloudflare 的边缘节点。如果你想完全本地运行,用:

pnpm wrangler dev --local

本地模式会启动一个 Miniflare 实例,模拟 KV、D1、R2、Durable Objects。数据存在本地文件里,不会影响线上。调试的时候用本地模式更快,因为不用等网络。

但本地模式有个限制:它不能完全模拟 Cloudflare 的网络环境。比如某些 API 的响应头可能不一样,某些边缘行为可能不同。所以最终测试还是要部署到线上。

注意:wrangler dev --local默认的持久化目录是.wrangler/state,如果你删掉这个目录,本地数据就没了。调试时如果发现数据不对,先检查这个目录。

7. 我踩过的坑和最后的小技巧

第一个坑是KV 的最终一致性。我在本地测试的时候,写入 KV 后立刻读取,能读到。但部署到线上后,写入后立刻读取,有时候读不到。这是因为 KV 是最终一致的,写入需要时间传播到所有边缘节点。解决办法是:写入后不要立刻读,或者把刚写入的数据放在 Durable Object 的内存里,读的时候先查内存,再查 KV。

第二个坑是D1 的并发写入。D1 基于 SQLite,写入是串行的。如果你同时发起多个写入请求,它们会排队。如果队列太长,后面的请求会超时。解决办法是:批量写入用batch(),把多个 INSERT 合并成一个事务。或者用 Queue 把写入异步化。

第三个坑是wrangler 的 secret 在本地不生效。wrangler secret put上传的 secret 只在线上可用,本地wrangler dev读不到。本地开发时需要在项目根目录建一个.dev.vars文件,把 secret 写进去:

AI_API_KEY=your-local-key

这个文件不要提交到 Git,加到.gitignore里。

最后分享一个小技巧:如果你经常需要切换不同的 Cloudflare 账号,可以用wrangler config命令管理多个配置文件。或者用环境变量CLOUDFLARE_API_TOKEN和CLOUDFLARE_ACCOUNT_ID,在 CI 里特别方便。我现在的做法是把这些变量写在.env文件里,用dotenv-cli加载,这样本地和 CI 的配置能保持一致。

这个cloudflare-os的思路后续还可以往很多方向扩展,比如接入更多的 AI 驱动、支持插件系统、做可视化的流程编排界面。但核心的骨架就是上面这些:Workers 做计算,KV/D1/R2 做存储,Durable Objects 做协调,wrangler 做部署,pnpm 做依赖管理。把这几个东西吃透,剩下的就是堆业务逻辑了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/28 23:11:11

从冰块融化理解Sigmoid函数的本质与应用

1. 从冰块融化理解Sigmoid函数的本质那天在厨房煮咖啡时&#xff0c;我盯着冰块在热水中逐渐融化的过程突然意识到&#xff1a;这不就是Sigmoid函数的物理呈现吗&#xff1f;作为在机器学习领域摸爬滚打多年的从业者&#xff0c;这个发现让我兴奋不已。Sigmoid函数作为神经网络…

作者头像 李华
网站建设 2026/10/28 23:10:45

Agent-Reach:构建AI Agent触达外部世界的可靠基础设施

1. 为什么需要Agent-Reach&#xff1a;Agent真正缺的不是脑子&#xff0c;是触达过去两年我一直在做LLM应用相关的项目&#xff0c;从最早简单的"大模型提示词"问答&#xff0c;到后来RAG检索增强&#xff0c;再到今年把重心彻底压在AI Agent上。绕了一大圈之后&…

作者头像 李华
网站建设 2026/10/28 23:10:01

PHP农业投资系统源码解析:投资返利、积分商城与转盘抽奖实现

简介&#xff1a;这是一套基于ThinkPHP框架开发的生态农业与牧业投资类项目源码&#xff0c;面向PHP开发者、农业互联网创业者及计算机专业学生&#xff0c;可用于学习认养模式系统的完整实现&#xff0c;或结合实际农业项目二次运营&#xff0c;如认养奶牛、认养菜园等场景。压…

作者头像 李华
网站建设 2026/10/28 23:08:45

PHP支付接口集成实战:PaySDK源码解析与避坑指南

简介&#xff1a;这份资源是基于PHP的PaySDK支付接口集成设计源码&#xff0c;面向需要为Web应用接入在线支付能力的PHP开发者&#xff0c;尤其适合希望快速集成支付宝、微信支付等主流渠道的中级开发者。项目以PHP与HTML为主要实现语言&#xff0c;兼容PHP 5.4及以上运行环境&…

作者头像 李华
网站建设 2026/10/28 23:08:00

MBA论文写作必备AI工具推荐与使用技巧

1. 为什么MBA论文写作需要AI工具辅助&#xff1f;写MBA论文的朋友都知道&#xff0c;这绝对是个体力活脑力活双重考验。从选题开题到文献综述&#xff0c;从数据分析到结论撰写&#xff0c;每个环节都需要投入大量时间精力。特别是对于在职MBA学员来说&#xff0c;白天上班晚上…

作者头像 李华
网站建设 2026/10/28 23:07:31

用Rust从零构建AI Agent框架:Agent-Reach架构设计与工程实践

我花了大半年时间&#xff0c;用 Rust 写了一个我称为 Agent-Reach 的 AI Agent 框架。名字起得没什么玄机&#xff0c;就是 Agent Reach&#xff0c;希望智能体真正“触达”外部世界&#xff1a;能读写本地文件、能把网页整理成 markdown、能在沙箱里安全执行代码、能把自己的…

作者头像 李华