DigitalOcean Functions 指南 2026 — 开发者无服务器计算
DigitalOcean Functions 是一项无服务器计算服务,让开发者将代码作为独立函数运行,无需管理或租赁服务器。它适合间断性流量或非均匀工作负载的任务,不同于运行 Droplet,后者要求你全天为机器付费,无论是否有人调用它。本指南将带你从基本概念、免费层、用 doctl serverless 部署的步骤,到真实用例和选择此方法前需了解的限制。 DigitalOcean Functions 基于 Apache OpenWhisk 架构构建,这是一个用于事件驱动代码执行的开源项目。每段代码被打包成一个"函数",分组为"包",多个包组成单个账户内的一个"命名空间"。一个 DigitalOcean 账户可以创建多个命名空间,清晰地分离开发、测试和生产等环境。 核心原则是函数不像 Droplet 上的进程那样全天闲置运行。相反,它们在触发器调用时"唤醒"——例如通过 DigitalOcean 自动设置的 API 网关的 HTTP 请求、用于基于时间的任务的 cron 计划,或来自其他系统的 webhook 事件。处理完成后,运行它的容器被清理(缩放到零),所以空闲期间没有成本——不同于 Droplet,后者无论流量如何都对整个开机时间收费。 DigitalOcean Functions 主要支持 Node.js、Python、Go 和通过自定义运行时的 PHP。开发者编写小函数文件,通过每种语言的包管理器声明依赖(npm、pip、go.mod),如常见做法,然后 DigitalOcean 在部署时自动将它们构建到容器镜像中,无需你自己编写 Dockerfile。 此模型适合那些不足以证明为整个月租用专用 Droplet 的任务——例如接收来自外部服务的 webhook 的端点、上传后处理图像的函数,或只在一天中运行几分钟的小定时任务。关于免费层和部署方法的详情见下一部分。
目录
什么是 Functions/无服务器计算
DigitalOcean Functions 是一项无服务器计算服务,让开发者运行代码作为独立函数,无需自己租赁或管理服务器。它适合运行偶尔发生或流量不均的工作——不同于运行 Droplet,后者要求你全时间为机器付费,无论是否有人使用。本文介绍了基础知识、免费层、用 doctl serverless 部署的步骤,以及在正式使用前需考虑的限制。 DigitalOcean Functions 建立在 Apache OpenWhisk 上,这是一个用于事件驱动代码执行的开源架构。每段代码被包装为一个"函数",分组为"包",多个包结合成每个账户的一个"命名空间"。一个 DigitalOcean 账户可以创建多个命名空间,清晰地分离开发、测试和生产等环境。 核心行为是函数不像 Droplet 上的进程那样持续运行——而是在触发器调用时"唤醒":通过 DigitalOcean 自动提供的 API 网关的 HTTP 请求、用于基于时间的工作的 cron 计划,或来自另一系统发送的 webhook 事件。处理完成后,容器停止(缩放到零),空闲期间成本为零,不同于 Droplet 全天收费。 DigitalOcean Functions 支持 Node.js、Python、Go 和通过自定义运行时的 PHP。开发者编写小函数文件,通过每种语言的标准包管理器设置依赖(npm、pip、go.mod),然后 DigitalOcean 在部署时自动将它们构建为容器镜像——无需 Dockerfile。 这种模式适合狭隘的任务,不足以在整个月租用单独的 Droplet——例如接收来自外部服务的 webhook 的端点、上传后调整大小或处理图像的函数,或每天运行几分钟的小定时任务。免费计划和部署工作流的详情见以下部分。
- 在 Apache OpenWhisk 架构上运行以实现事件驱动执行
- 支持 Node.js、Python、Go 和 PHP(通过自定义运行时)
- 组织为函数 → 包 → 命名空间的层级
- 使用零成本时自动缩放到零
- 对于间断性工作负载比需要连续运行时间的任务更好
免费层:90,000 GiB-秒/月
用户经常问到的一点是:DigitalOcean Functions 提供每月 90,000 GiB-秒的免费配额,超过此限制后无单独的调用费用。GiB-秒单位由函数使用的内存(以 GiB 计)乘以实际运行时间(以秒计)计算。例如,设置为 256 MiB(0.25 GiB)的函数运行 1 秒每次调用消耗 0.25 GiB-秒——意味着你的免费 90,000 GiB-秒配额在产生额外费用前覆盖大约 360,000 次调用/月(90,000 除以 0.25)。
从连续运行时的角度来看,相同的 256 MiB 函数在免费配额内每月运行约 100 小时(90,000 GiB-秒除以 0.25 GiB 等于 360,000 秒,或大约 100 小时)。设置更高的函数,如 512 MiB 或 1 GiB,每秒消耗更多资源,所以会更快地耗尽运行小时数。
需要注意的一个细节:系统在你的账户中的所有函数合并计算配额——不是按命名空间或按函数分别计算。因此如果你在同一账户下的命名空间中运行多个项目,请通过 DigitalOcean 控制面板或命令 doctl serverless activations list 追踪总使用情况以查看每个调用的历史。
如果使用超过了一个月的免费配额,DigitalOcean 对超出的 GiB-秒按照你应该在其当前定价页面上验证的费率收费,因为它们可能会改变。对于测试的新团队,新账户在注册后 60 天内获得有效的 $200 试用额度,可以在评估阶段覆盖测试成本。
- 每月免费配额 90,000 GiB-秒,无单独调用费
- GiB-秒 = 内存(GiB)× 运行时间(秒)
- 256 MiB 函数在免费层内每月运行约 100 小时
- 配额在整个账户中共享,不按命名空间划分
- 用
doctl serverless activations list监控使用情况
用 doctl serverless 创建和部署函数
在 DigitalOcean 上部署函数通过 doctl 进行,即官方 DigitalOcean CLI,在单独添加无服务器插件后。首先用 doctl serverless install 安装插件,然后用 doctl serverless connect 连接你的账户,这会提示你选择一个命名空间和区域(Functions 在除 atl1 和 ric1 外的几乎所有 DigitalOcean 数据中心都可用)。
连接后,用 doctl serverless init my-functions --language js 创建一个示例项目。此命令生成一个包含 project.yml 文件的项目文件夹和一个名为 sample 的示例包,包含一个 hello 函数。文件组织为 packages/sample/hello/index.js——按包名,然后按函数名。
根据需要编辑 index.js 中的代码:添加逻辑以捕获 HTTP 请求参数、调用外部服务等。然后更新 project.yml 为每个函数设置内存、超时和环境变量。准备就绪时,用一条命令部署:doctl serverless deploy my-functions。系统自动将你的代码构建到容器镜像并推送到你连接的命名空间,无需 Dockerfile。
部署完成后,用 doctl serverless functions list 列出所有函数,并使用 doctl serverless functions get sample/hello --url 获取特定函数的 HTTP URL。通过 curl 测试该 URL,或通过 CLI 用 doctl serverless functions invoke sample/hello --param name World 直接调用——对于在开发中测试而不公开端点很方便。
问题出现时,用 doctl serverless activations logs --last 向后检查执行日志,它显示每次运行的运行时错误和时序数据。此工作流让你快速部署新的或更新的函数,无需 SSH 进入服务器。
doctl serverless install 然后 doctl serverless connect 安装插件- 用
doctl serverless install然后doctl serverless connect安装插件 - 用
doctl serverless init my-functions --language js创建项目 - 用一条命令部署整个项目:
doctl serverless deploy my-functions - 用
doctl serverless functions get和invoke查看 URL 并测试
用例:Webhooks、图像处理、定时任务
DigitalOcean Functions 对于偶尔工作而不是连续运行时间表现最佳。三个常见用例是 webhook 接收器、图像处理和定时任务。
Webhook 接收器是最频繁的场景:捕获当代码被推送到 GitHub 时的通知、接收来自 Stripe 或其他支付处理器的支付事件,或从 LINE Messaging API 获取消息。编写一个函数接收 HTTP POST、验证载荷签名,然后处理逻辑——例如写入数据库或转发到另一个队列。由于 webhook 不可预测地到达,运行 Functions 比让 Droplet 在线等待入站请求要好。
图像处理是事件驱动架构的另一个强有力适合:一个函数在用户上传照片到 Spaces(对象存储)后运行,需要以多种大小创建缩略图、压缩文件或转换格式。这项工作每次运行很短,但基于用户行为不规则地发生。用你的语言的图像库编写函数——例如 Node.js 的 sharp 或 Python 的 Pillow——并让它在新文件到达时触发。
Cron 任务或计划任务处理定期的、基于时间的工作:每小时从外部 API 同步数据、发送每日摘要报告或清理过期的记录。用 doctl serverless triggers create sample/hello --type scheduled --param cron "0 * * * *" 设置一个,它使用标准的 crontab 语法。这替代了只为运行小定时任务租用专用 Droplet 的需要。
所有三个都共享一个特点:短工作负载、不可预测的频率、无需在调用之间保持状态——恰好是 Functions 最好处理的,不同于需要连续处理或内存中会话的工作。
- Webhooks:从 GitHub、支付网关、LINE Messaging API 接收事件
- 图像处理:上传到 Spaces 后创建缩略图和压缩图像
- 定时任务:用
doctl serverless triggers create --type scheduled计划 - 最适合短、不常见的工作负载,无调用之间的持久状态
与自运行 Droplet 的限制对比
虽然 Functions 简化了某些任务,但与完整 Droplet 控制相比有权衡。在转移所有内容到无服务器前考虑这些。 首先:每次调用的执行超时。Functions 为快速任务构建,不是持久连接或长轮询等长时间运行的或阻塞性操作。确切的超时限制应在最新文档中检查,因为 DigitalOcean 可能调整它。这与 Droplet 形成对比,后者进程可以按需运行,只要机器保持开机。 其次:无调用之间的持久磁盘或状态。每个函数调用可能在新容器上生成(冷启动)或重用未清理的容器(热启动),但你不能指望在过去调用中写入的文件在下一个调用中存在。任何必须在运行之间存活的数据必须存在于单独的托管数据库或 Spaces 中,而不是函数的本地文件系统。 第三:运行时和依赖灵活性有限。Droplet 让你安装任何东西、控制内核、管理系统包或自由运行自定义二进制。Functions 限制在 DigitalOcean 提供的运行时(Node.js、Python、Go、通过自定义运行时的 PHP)。如果你需要在标准容器中不方便的专用软件,Droplet 可能更简单。 第四:区域覆盖。Functions 并非随处可用——特别是 atl1 和 ric1 仍然不支持。Droplets、Kubernetes、负载均衡器和 VPC 跨越所有 15 个区域。如果你的团队有严格的区域要求,先验证 Functions 可用性。 总结:Functions 最适合短、偶尔、无状态的工作负载。Droplets 对连续运行时、完整环境控制或资源密集的任务仍然需要。
- 每次调用有执行超时——不适合长时间运行的连续处理
- 无持久磁盘;数据必须存在于函数外(托管数据库或 Spaces)
- 运行时限于 DigitalOcean 提供的语言,不同于 Droplet 的完整控制
总结:何时选择 DigitalOcean Functions
权衡以上所有,Functions 和 Droplets 之间的决定主要取决于工作负载类型而不是偏好。如果你的任务流量不均、偶尔发生或在几秒内完成——例如 webhook、基本图像工作或不常见的定时任务——Functions 在成本上胜出,因为你在空闲期间不支付任何费用。免费 90,000 GiB-秒/月覆盖许多中小型项目而不花费一分钱。 相反,如果你的应用必须不停地运行、需要完整的运行时控制、需要持久内存中状态或获得稳定的高流量,其中按使用付费成本可能超过固定 Droplet 价格,那么在 Droplet 或 App Platform 上运行更有意义。 实际上,许多团队混合两者:在 Droplet 或 App Platform 上像往常一样运行主后端,然后仅将事件驱动或偶尔的任务(如 webhook 和定时任务)路由到 Functions。这减轻了主服务器负载并保持成本可控,而不用把所有东西都无服务器化。 DigitalOcean 的新用户在注册后 60 天内获得有效的 $200 试用额度——足以按照本指南测试构建和部署真实函数,加上与 Spaces 或托管数据库实验以查看哪种架构适合你的项目,然后再长期承诺。
- 短、不常见的工作负载使 Functions 比运行的 Droplet 更便宜
- 连续、复杂或全天在线应用支持 Droplet 或 App Platform
- 许多团队混合两者:主后端在 Droplet 加事件驱动的任务在 Functions 上
- 新账户可以用有效 60 天的免费 $200 额度测试
常见错误及修复方法
当你在真实项目中开始使用 DigitalOcean Functions 时,某些错误频繁出现,通常直到它们影响用户或成本才被注意到。要注意的四个关键问题是冷启动延迟、无意中超出免费配额、忘记环境变量或秘密,以及不匹配的运行时版本。
冷启动延迟是新手最常见的陷阱。当一个函数长时间未被调用时,其容器按照缩放到零的原则被清理。下一次调用必须在运行前启动一个新容器,使第一个响应比平时慢。如果你的函数支持网页,其中用户等待即时结果,用 doctl serverless functions invoke sample/hello --param name test 在不同的间隔多次测试真实延迟以测量冷和热调用之间的差距。围绕它规划你的 UX——在等待结果时显示加载状态。
在没有注意的情况下超出免费 90,000 GiB-秒配额经常发生,通过为实际需要的东西设置过高的内存,或具有在缓慢外部 API 上等待的逻辑。由于 GiB-秒同时考虑内存和运行时,一个配置了过多内存的函数但没有全部使用会为无用的东西耗尽配额。定期用 doctl serverless activations list 检查使用情况,并调整 project.yml 中的内存以匹配实际需要,而不是猜高。
忘记设置环境变量或秘密绊倒许多人。你在本地配置的值——如开发期间的 .env 文件——不会自动随部署发送。你必须在 project.yml 中每个函数的环境或参数部分中定义它们。如果遗漏,函数在尝试读取缺失值时立即崩溃。始终在部署后立即用 doctl serverless functions invoke 测试,而不是假设成功意味着所有工作正常。
最后,运行时版本不匹配发生在你为更新的 Node.js 或 Python 编写代码时,但 project.yml 仍然指定 DigitalOcean 提供的较旧运行时版本。部署可能成功但执行失败,因为语法不被支持。始终指定与你实际测试的运行时版本匹配的版本,并在部署生产工作前在官方文档中检查最新支持的版本。
- 冷启动:部署前用
doctl serverless functions invoke测试真实延迟 - 定期通过
doctl serverless activations list监控配额以避免意外超出费用 - 在 project.yml 中始终设置环境变量/秘密;本地 .env 文件不会自动部署
最佳实践
在需要长期维护的多个函数的真实项目中运行 Functions 时,几个实践可以减少问题并缓解维护。四个关键主题是将函数设计为无状态和幂等的、始终一致地监控调用、用清晰的结构组织项目,以及在实时部署前测试。
始终将函数设计为无状态和幂等的。每个调用可能在不同的容器上运行,所以不要依赖于来自早期调用的变量或文件持久化。任何必须在调用间存活的数据都在函数外——在托管数据库或 Spaces。还要设计以便再次调用函数产生相同的结果且无副作用(幂等):例如,如果 webhook 可能在失败时重试,检查你是否已处理该请求,然后再写入重复记录。
定期监控调用,不仅仅是部署后。使用 doctl serverless activations list 查看所有调用历史和 doctl serverless activations logs --last 深入挖掘错误或意外的运行时。如果任何函数频繁出错或运行时间远长于预期,立即调查日志,而不是等待用户抱怨。
对于多函数项目,按业务域组织包以明确性——如 packages/webhooks、packages/image-processing、packages/scheduled-tasks——而不是将所有东西转储到一个包中。packages/<package-name>/<function-name>/index.js 布局使 project.yml 可读,并且随着项目规模扩大,仅变更部分的部署更容易。
始终在实时部署前测试。为每个函数的核心逻辑编写单元测试,与 DigitalOcean 特定部分分离,这样你可以在本地运行测试而无需每次调整代码时部署。准备就绪时,部署到单独的过程中命名空间,调用它以确认它工作,然后部署到生产。这减少了破损代码击中真实用户的风险。
- 将函数设计为无状态;持久数据保存在外部(托管数据库/Spaces)
- 使函数幂等以安全处理重试,无重复副作用
- 始终使用
doctl serverless activations list和logs --last一致监控