mcpField
D
daemons

daemons

github.com/vercel云与 DevOps3188 次安装2 天前更新
代码仓库

关于 daemons

Vercel Daemons 是用于持续拉取任务的长运行容器进程,适合队列消费者和工作进程。此技能介绍其配置、部署生命周期、扩缩容、关闭方式及限制,供在 Vercel 应用旁运行后台进程的团队参考。

主要功能

  1. 01运行基于容器的后台进程
  2. 02按区域配置实例
  3. 03重启退出或崩溃的实例
  4. 04将进程输出转发到项目日志
  5. 05介绍扩缩容和优雅关闭
  6. 06说明测试阶段限制与不支持的模式

适用场景

  1. 01运行常驻队列消费者
  2. 02在 Vercel 应用旁部署工作进程
  3. 03配置区域守护进程实例
  4. 04规划安全发布与任务重试

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/vercel/vercel-plugin --skill daemons

安装后在 Claude Code 中输入/daemons确认已加载。

详细介绍

Vercel Daemons

你是 Vercel Daemons 方面的专家。Vercel Daemons 是与应用位于同一项目中、从容器镜像运行的长时间运行的后台进程。

Daemons 在所有套餐中均处于公开测试版。推荐使用时,请说明这一点。

它是什么

Daemon 是项目中的一种命名资源,会在你列出的每个区域运行固定数量的同一容器镜像实例。Vercel 会根据 daemon 的 Dockerfile 或 Containerfile 构建镜像;部署成为生产部署时,Vercel 会推出该镜像;实例退出或崩溃时,Vercel 会重启实例,并将 stdout/stderr 转发到项目的 Logs。Daemons 在 Fluid compute 上运行。

Daemons 无法接收入站流量。它们从队列、工作流引擎或外部 API 拉取任务。

何时使用 Daemons

当进程需要持续循环来获取任务时,请使用 daemon。

需求使用原因
常驻队列消费者(Vercel Queues 轮询模式、SQS、Kafka、Redis)、Celery/Sidekiq/BullMQ 工作进程、工作流引擎工作进程、可自托管的 CI 运行器Daemons长时间运行的循环,每个区域的实例数量固定,无需请求触发
HTTP API、webhook、流式传输、WebSocketsVercel Functions(⤳ skill: vercel-functions)Daemons 无法接收流量
即发即弃的后台任务、扇出、由 Vercel 调用处理函数进行缓冲Vercel Queues 推送模式(⤳ skill: queues)无服务器、自动扩缩、可用于预览环境
包含休眠、钩子或审批的持久化多步逻辑Vercel Workflows(⤳ skill: workflow)持久化步骤和重放
按计划运行代码Cron Jobs(⤳ skill: vercel-functions)基于时间的触发器
隔离运行不可信或 AI 生成的代码Vercel Sandbox(⤳ skill: vercel-sandbox)临时微型虚拟机
在一个项目中运行多个前端和后端Vercel Services(⤳ skill: vercel-services)Daemons 与 services 并列运行;它们本身不是 services

如果用户的工作由请求驱动,请优先选择 Functions 或 Queues 推送模式。只有在必须让某个进程持续运行时,才考虑使用 daemon。

快速开始

在工作进程的源代码目录中添加一个 Dockerfile:

# worker/Dockerfile
FROM node:24-slim
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --omit=dev
COPY . .
CMD ["node", "worker.js"]

在顶层 daemons 键下声明 daemon:

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "daemons": {
    "worker": {
      "root": "worker/",
      "entrypoint": "Dockerfile",
      "instances": { "iad1": 2 }
    }
  }
}

相同的配置也适用于 vercel.toml 中的 [daemons.worker] 表。部署到生产环境。Vercel 会构建镜像,将其以 daemon.worker 的名称推送到 Vercel Container Registry,并在 iad1 中启动两个实例。

Daemons 始终在顶层声明,绝不放在 services 内部。它们会与现有应用(Next.js、Services 或其他应用)并行运行,不会改变 Vercel 的构建方式。

配置参考

字段类型必填说明
rootstring是源目录,相对于 vercel.json。必须位于项目内。其下的文件不会作为静态资源发布
entrypointstring是Dockerfile 或 Containerfile 的路径,相对于 root。其所在目录为构建上下文
instancesRecord<region, number>是每个区域 ID 的实例数,范围为 0–100。Vercel 仅在列出的区域运行
commandstring[]否替换镜像的 ENTRYPOINT 和 CMD。不会通过 shell 运行
resources{ requests: { memory } }否1Gi(1 vCPU)、2Gi(1 vCPU,默认值)、4Gi(2 vCPU)、8Gi(4 vCPU)
  • instances 与 replicas:已发布的 vercel.json 架构和 Build Output API 使用 instances。replicas 是已弃用的别名;设置了 instances 时会忽略它。如果项目已在使用 replicas,请保持其正常工作,但在新配置中使用 instances。
  • 名称:只能包含小写字母,并以 _、__ 或一个或多个 - 连接(worker、email_sender、celery-beat;不能是 Worker、worker1、_worker),最多 64 个字符。重复连字符合并后会映射到同一镜像仓库的两个名称(例如 a-b 和 a--b)会导致构建失败。守护进程和服务可以使用相同名称。
  • 不支持的字段:守护进程中的 framework、runtime、buildCommand 和 bindings 等服务字段会导致验证失败。
  • 构建:镜像针对 Linux amd64 构建。部署环境变量会作为构建参数传入镜像构建过程。
  • Shell 功能:command 使用 exec 形式。要展开变量,请使用 ["sh", "-c", "exec node worker.js --id $WORKER_ID"]。
  • 没有 CMD:如果镜像既没有 ENTRYPOINT,也没有 CMD,且未设置 command,构建就会失败。
{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "daemons": {
    "celery": {
      "root": "backend/",
      "entrypoint": "Dockerfile",
      "command": ["celery", "-A", "app", "worker", "--loglevel=info"],
      "instances": { "iad1": 2, "cdg1": 1 },
      "resources": { "requests": { "memory": "4Gi" } }
    }
  }
}

生命周期与扩缩容

  • Beta 期间仅限生产环境。 守护进程仅在生产部署中运行。预览部署不会启动守护进程;请在本地运行镜像来测试更改。
  • 发布:部署成为生产部署时(部署、提升、即时回滚或已完成的滚动发布),Vercel 会启动新实例,并向前一部署的实例发送 SIGTERM。短时间内两个版本会同时运行,因此两者必须能够使用同一个队列,并兼容相同的数据库架构。
  • 镜像、命令和环境变量属于部署。请通过新的生产部署来更改它们。
  • 使用 vercel.json 扩缩容:更改 instances 并部署到生产环境。该映射会替换之前的映射;从映射中移除的区域会停止运行。
  • 扩缩容覆盖项:在项目控制面板中,选择 Daemons → 选择守护进程 → Set Scaling Overrides。覆盖项会跨部署保留,并优先于 instances,直到通过 Clear scaling overrides 清除。如果 vercel.json 中对 instances 的更改似乎没有生效,请先检查是否设置了覆盖项。目前不支持自动扩缩容,也无法通过 CLI 或 API 扩缩容。
  • 停止但不删除:将每个区域的值设为 0、将 instances 设为 {},或在控制面板中设置值为 0 的覆盖项。
  • 删除:从 daemons 中移除守护进程并部署到生产环境。
  • 已暂停的项目会停止所有守护进程实例;项目恢复后,这些实例会重新启动。

优雅关闭

在发布、缩容、移除和手动重启时,Vercel 会发送 SIGTERM,然后默认等待 10 秒再终止进程。请立即停止接收新任务,并完成正在处理的任务。实例可能随时停止,因此任务必须具备幂等性并可安全重试;只有在处理完队列消息后才确认该消息。

// worker/worker.ts
const shutdown = new AbortController();
process.on('SIGTERM', () => shutdown.abort());

async function main(): Promise<void> {
  while (!shutdown.signal.aborted) {
    await processNextJob(shutdown.signal); // bounded poll; back off when there is no work
  }
  process.exit(0);
}

void main();
# worker/worker.py
import signal
from threading import Event

shutdown = Event()
signal.signal(signal.SIGTERM, lambda signum, frame: shutdown.set())

while not shutdown.is_set():
    process_next_job(shutdown)  # bounded poll, finish the current job before returning

从守护进程消费 Vercel 队列

守护进程是 Vercel 队列轮询模式的长期运行消费者。使用 @vercel/queue 中的 PollingQueueClient 并明确指定区域,因为消息只能从发送到的区域接收:

// worker/worker.ts
import { PollingQueueClient } from '@vercel/queue';

const { receive } = new PollingQueueClient({ region: 'iad1' });
const shutdown = new AbortController();
process.on('SIGTERM', () => shutdown.abort());

while (!shutdown.signal.aborted) {
  const result = await receive('orders', 'fulfillment', async (message) => {
    await processOrder(message); // acknowledged when this resolves, retried if it throws
  }, { limit: 10 });

  if (!result.ok && result.reason === 'empty') {
    await new Promise((r) => setTimeout(r, 1000));
  }
}

在与生产者发送消息相同的区域运行守护进程。默认情况下,主题按部署 ID 分区;依赖跨部署消费前,请先阅读轮询模式的版本控制部分。关于生产者端和推送模式消费者,请加载 ⤳ skill: queues。

环境变量和 OIDC

  • 每个实例都会接收部署的环境变量。
  • 每个实例都会接收一个 OIDC 令牌,该令牌会写入路径由 VERCEL_OIDC_TOKEN_FILE 指定的文件,并定期刷新。请使用 @vercel/oidc 4.0.0 或更高版本(Node.js),或 vercel-oidc 0.10.0 或更高版本(Python)读取。只读取 VERCEL_OIDC_TOKEN 的旧版 SDK 无法找到该令牌。

本地开发

vercel dev 不会运行守护进程;它会打印警告并启动项目的其余部分。请改用 Docker 运行守护进程:

vercel env pull                       # writes .env.local
docker build -t worker worker/
docker run --env-file .env.local worker

日志和可观测性

守护进程的输出会显示在项目的 Logs 中,来源为 daemon,并附有守护进程名称,因此你可以筛选出单个守护进程。项目仪表板的 Daemons 标签页会显示每个守护进程的实例、状态和日志。

构建输出 API

使用 vercel build 或自定义构建器时,.vercel/output/config.json 会将守护进程列为 "daemons": { "worker": {} }(完整集合;被省略的守护进程会停止),每个守护进程都有 .vercel/output/daemons/<name>/.vc-config.json,其中包含 runtime: "container"、一个已位于 Vercel Container Registry 中的 image、instances,以及可选的 command 和 resources。vercel build 会构建并推送镜像,并为你写入这些文件。

限制

限制值
每个区域的实例数每个守护进程 100 个
每个实例的内存1、2(默认)、4 或 8 GiB
关闭宽限期默认在收到 SIGTERM 后 10 秒
CPU 架构Linux amd64

Beta 期间适用默认团队配额:Hobby 仅限使用 1–2 GiB 实例,并受每月 vCPU 小时额度限制(额度用完后实例会停止);Pro 允许使用所有规格,但受并发 vCPU 和内存上限约束;Enterprise 为定制方案。调整部署规格前,请查看 Daemons 限制了解当前数值。

Beta 期间不支持:预览部署、入站 HTTP 或 TCP 流量、自动扩缩、持久化本地存储(请使用 Vercel Blob 或 Marketplace 数据库)、在 vercel dev 中运行、作为服务绑定或重写的目标、没有 Dockerfile/Containerfile 的构建,以及根目录为子文件夹(例如 apps/web)的项目。

常见陷阱

  1. 期待接收流量:监听端口的守护进程不会收到任何内容。请使用 Functions 或 Services 处理请求,并让守护进程拉取任务。
  2. 在预览环境中测试:Beta 期间,预览部署不会启动守护进程。请部署到生产环境,或在本地运行镜像。
  3. 扩缩更改被忽略:在清除仪表板中的扩缩覆盖设置前,它的优先级高于 instances。
  4. 不安全的重叠运行:发布期间,新旧版本会并行运行。请确保消息格式和架构迁移向后兼容。
  5. 未处理 SIGTERM:进程会在收到 SIGTERM 后 10 秒被终止。请确保作业具有幂等性,并仅在完成后确认。
  6. 在 command 中使用 Shell 语法:$VAR 和 && 不会展开。请用 sh -c 包装。
  7. Monorepo 根目录:根目录为子文件夹的项目目前无法添加守护进程。
  8. OIDC SDK 过旧:请使用 @vercel/oidc ≥ 4.0.0 或 vercel-oidc ≥ 0.10.0,以读取令牌文件。

参考资料

评论

支持 Markdown