Ente 的 Cloudflare Workers 基础设施:基于 npm Workspaces 的多 Worker 部署与日志实践
2026/9/12 11:46:58 网站建设 项目流程

Ente 的 Cloudflare Workers 基础设施:基于 npm Workspaces 的多 Worker 部署与日志实践

【免费下载链接】ente💚 End-to-end encrypted cloud for everything.项目地址: https://gitcode.com/GitHub_Trending/en/ente

导读

本文基于 Ente 仓库中 infra/workers/README.md 及其源码,系统讲解 Ente 如何以「单一 npm 仓库 + 多个独立部署的 Cloudflare Worker」组织其边缘计算基础设施。你将掌握:多个 Worker 共享依赖与 TypeScript 配置的 monorepo 结构、使用 Wrangler 完成登录/部署/实时日志的标准流程、通过tail_consumers将 Worker 日志聚合到 Grafana 的监控链路,以及从零新建或从 Cloudflare Dashboard 迁移既有 Worker 的两种实践路径。

一、概览:一个仓库、多个 Worker 的 monorepo 结构

Ente 将全部 Cloudflare Worker 收敛在infra/workers/目录下,整体定位是「npm workspaces 的集合」:每个 Worker 是一个独立的 workspace,共享根部的 package.json 与 tsconfig.base.json,但彼此独立部署。

从目录结构看,目前共有 10 个 Worker,每个都包含标准的src/index.tspackage.jsontsconfig.jsonwrangler.toml四件套:

Worker 目录主要职责(从源码推断)
cast-albums面向 Cast 的相册相关边缘接口
csp-reporter接收并聚合 Content-Security-Policy 违规报告
data-puller数据拉取类任务
files文件相关边缘处理
health-check周期探活 API 服务并发送告警
public-albums公开相册的边缘入口
sentry-reporter重写并转发 Sentry 事件 DSN
tail消费各 Worker 的日志并推送至 Loki/Grafana
thumbnails缩略图代理,附带响应安全加固
uploader上传入口

根部 package.json 的workspaces: ["*"]声明使所有子目录自动成为 workspace,同时锁定统一工具链版本:wrangler 4.120.1typescript 6.0.3@cloudflare/workers-types 5.20260804.1,并使用prettier 3.9.6统一代码风格。值得一提的工程细节是:根 tsconfig 中"types": ["@cloudflare/workers-types"]让所有 Worker 的 TypeScript 代码无需额外安装类型包即可获得RequestResponseExecutionContext等运行时类型。

二、部署工作流:登录、部署、日志与退出

1. 安装依赖

所有 Worker 共享同一份锁文件,因此只需在仓库根部执行一次:

npm ci

npm ci会根据 package-lock.json 做干净安装,保证 CI 与本地环境依赖完全一致。

2. 登录并部署

Wrangler 凭据在所有 workspace 之间是共享的,因此只需要登录一次,即可对任意 Worker 执行部署。以health-check为例:

npm exec --workspace health-check -- wrangler login npm exec --workspace health-check -- wrangler deploy

--workspace health-check会进入对应 workspace 读取其 wrangler.toml。要部署其他 Worker,只需把health-check替换为目标 workspace 名(例如npm exec --workspace uploader -- wrangler deploy)。

每个 Worker 独立部署的意义在于:单个 Worker 的发布不影响其他服务,可以按各自节奏灰度与回滚。

3. 实时查看线上日志

部署后可以拉取线上运行日志进行排查:

npm exec --workspace health-check -- wrangler tail

wrangler tail会实时流式输出该 Worker 的 console 输出、异常与请求记录,适合在发布后立即观察运行状况。

4. 完成后退出登录

npm exec --workspace health-check -- wrangler logout

遵循用完即退的凭据管理习惯,避免共享机器上遗留长期有效的认证状态。

三、创建新 Worker 的两种路径

路径一:复制现有 workspace(推荐)

仓库文档明确建议「Copy an existing workspace」,即复制一个现成的 Worker 目录作为起点。这样做可以完全避开 Cloudflare 官方模板中大量与本项目无关的样板代码(boilerplate),新 Worker 天然继承本仓库的tsconfig、工具链版本与目录规范,只需修改wrangler.tomlnamemainroutes/triggerssrc/index.ts的业务逻辑即可。

路径二:从零创建

如果需要从空模板开始,使用 Cloudflare 官方脚手架:

npm create cloudflare@latest

路径三:从 Cloudflare Dashboard 导入既有 Worker

如果某个 Worker 已经存在于 Cloudflare Dashboard 中(例如过去在网页控制台手工创建),可以将其导入为本地项目:

npm create cloudflare@2 existing-worker-name -- --type pre-existing --existing-script existing-worker-name

其中--type pre-existing表示导入既有脚本,--existing-script指定 Dashboard 中的脚本名。导入后即可纳入本仓库的 monorepo 统一管理。

四、日志链路:tail_consumers 与 Grafana 聚合

1. 附加日志消费 Worker

任何需要上报日志的 Worker,只需在其wrangler.toml中加入:

tail_consumers = [{ service = "tail" }]

这一配置告诉 Cloudflare:该 Worker 的所有 trace(console 输出与未捕获异常)将实时转发给名为tail的 Worker 处理。仓库中health-checkuploaderpublic-albumscast-albums等 Worker 均已接入,例如 uploader/wrangler.toml 与 public-albums/wrangler.toml。

2. tail Worker:把日志推送进 Loki

tail/src/index.ts 实现了日志汇聚逻辑:

  • 导出tail(events: TraceItem[], env)处理程序,遍历事件并仅筛选出包含 console 日志或未捕获异常的事件(event.logs.length || event.exceptions.length),丢弃纯请求元数据,控制写入量;
  • 对每条日志调用pushLogLine,将事件 JSON 序列化后以 Loki 的 streams 格式 POST 到LOKI_PUSH_URL
  • 时间戳按纳秒(timestampMs * 1e6)写入 Loki 要求的时间格式,并打上stream: { job: "worker" }标签便于在 Grafana 中筛选。

其 wrangler.toml 中声明的两个变量均通过 Cloudflare Dashboard 以 Secret 形式注入(不在源码中落盘):

[vars] # Added as a secret via the Cloudflare dashboard # LOKI_PUSH_URL = "https://${loki_base_url}>/loki/api/v1/push" # LOKI_AUTH = "${btoa(user:pass)}"

其中LOKI_AUTHuser:pass的 base64 编码——代码注释特别说明,Worker 的fetch不接受在 URL 中携带凭据,因此只能通过Authorization: Basic请求头传递,即 tail/src/index.ts 中的Authorization: \Basic ${env.LOKI_AUTH}``。

3. 可观测性设计意图

tailWorker 的注释点明了一个刻意的设计:如果 Loki 宕机导致tail自身抛异常,代码不做捕获,使其在该 Worker 的统计中计为一次「error」。这样日志链路的健康状态会直接反映在 Worker 级指标中,避免「日志悄悄丢失」的盲区。最终所有 Worker 的日志汇聚到 Grafana,与仓库 infra/services/grafana 部署的监控体系打通,形成「边缘日志 → Loki → Grafana」的闭环。

五、源码印证:从配置与实现看 Worker 的典型形态

1. health-check:Cron 驱动的探活与告警

health-check/wrangler.toml 展示了「非 HTTP」型 Worker 的配置范式:

name = "health-check" main = "src/index.ts" compatibility_date = "2026-04-23" # Disable the default route, this worker does not handle fetch. workers_dev = false tail_consumers = [{ service = "tail" }] [vars] # Added as a secret via the Cloudflare dashboard # NOTIFY_URL = "" # CHAT_ID = "" [triggers] crons = [ "*/1 * * * *" ]

关键点:

  • workers_dev = false:该 Worker 不处理 fetch 请求,禁用默认开发路由;
  • [triggers] crons:每分钟触发一次scheduled处理器;
  • NOTIFY_URLCHAT_ID同样以 Dashboard Secret 注入,从代码看是 Telegram Bot 的推送地址与聊天 ID。

对应实现 health-check/src/index.ts 的探活逻辑是:ctx.waitUntil(ping(env, ctx))异步执行,请求https://api.ente.com/ping;若 5 秒内未返回或返回非 2xx,则通过sendMessage向 Telegram 推送告警,消息内容包含失败原因(如Ping failed (HTTP 500)或网络异常信息),并附带on ${Date()}的服务端时间戳。

2. thumbnails:带安全加固的反向代理

thumbnails/src/index.ts 是典型的 HTTP 型 Worker:对GET请求把fileID透传给上游https://api.ente.com/files/thumbnail/v3/${fileID},并在转发时设置X-Forwarded-For为客户端真实 IP(取自CF-Connecting-IP),让上游能感知真实来源。返回响应前执行hardenResponseHeaders安全加固:设置X-Content-Type-Options: nosniffContent-Security-Policy: sandbox allow-downloadsX-Frame-Options: DENYReferrer-Policy: no-referrer;若内容类型为 HTML/XML/SVG 等可执行类型,则强制追加Content-Disposition: attachment,防止 XSS 与页面嵌套。同时通过isAllowedOrigin只允许*.ente.com*.ente.io*.ente.shlocalhostente://app来源访问,强化 CORS 边界。

3. csp-reporter:收集前端安全违规报告

csp-reporter/src/index.ts 接收各客户端 POST 来的 CSP 违规报告,以[csp-report]前缀写入日志,经由tail_consumers进入 Loki,供 Grafana 检索(源码注释直接给出了对应的 LogQL 查询思路:{job="worker"} |= \[csp-report]` | json log="logs[0]" | keep log`)。

4. sentry-reporter:DSN 重映射的灰度技巧

sentry-reporter/src/index.ts 展示了非常实用的工程技巧:将已发布客户端中固定的 Sentry DSN 映射到当前项目的 DSN。它解析事件 envelope 头中的dsn,若命中 dsnMappings(如 photos-mobile、auth-mobile 的旧 DSN),则重写事件体与公钥后转发到https://${dsn.host}/api/${projectId}/envelope/。这样即使 Sentry 项目被重建,也无需重新发布客户端即可让错误继续上报到新项目。同时只接受sentry.ente.com/sentry.ente.io的 HTTPS DSN,拒绝其他来源。

5. uploader / public-albums / cast-albums:自定义域名路由

这几个面向公网的 Worker 通过routes绑定自定义域名,例如 uploader/wrangler.toml:

routes = [ { pattern = "uploader.ente.com", custom_domain = true }, { pattern = "uploader.ente.io", custom_domain = true } ]

custom_domain = true表示这些域名是托管在 Cloudflare 上的自定义域,请求直接由 Worker 处理,无需 Zone 路由配置。

六、工程实践要点总结

综合 README 与源码,Ente 的 Workers 体系可以归纳出四条可复用的实践:

  1. monorepo 但独立部署:共享 package.json 与 tsconfig.base.json(后者配置了noEmit——Cloudflare Workers 运行时原生支持 TypeScript,tsc仅用于类型检查),每个 Worker 却拥有独立的wrangler.toml与发布节奏,兼顾依赖统一与部署隔离;
  2. 一套凭据全局复用:Wrangler 登录态跨 workspace 共享,用npm exec --workspace <name> -- wrangler <cmd>统一操作,避免在每个目录重复登录;
  3. 日志统一走 tail 消费:任何 Worker 一行tail_consumers即可接入 Loki/Grafana,并通过「tail 自身异常不捕获」的设计让日志链路故障可被监控到;
  4. 敏感配置一律走 SecretNOTIFY_URLCHAT_IDLOKI_PUSH_URLLOKI_AUTH等均在wrangler.toml中以注释占位、经 Cloudflare Dashboard 注入,源码中不出现任何明文凭据。

如需深入某个 Worker 的实现细节,可继续阅读对应的src/index.tswrangler.toml;整个 Worker 集合的依赖与工具链版本见 infra/workers/package.json。

【免费下载链接】ente💚 End-to-end encrypted cloud for everything.项目地址: https://gitcode.com/GitHub_Trending/en/ente

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询