你开了一家小饭馆,午市挤爆、下午冷清。如果天天养十位固定厨师,闲时无事可做;如果只养两位,忙时又应付不来。于是你决定改成“按需食堂”——不养固定灶台,接到订单才临时叫厨师上灶。这正是 Serverless / FaaS 的朴素原型:把“做菜的能力”租到云端,按单计费、用完即走。但真到落地时,你得当“食堂管理员”亲自搭建这套按需系统,市面上有两套现成的方案:OpenFaaS 像“保温菜摊”,每道菜一口锅常驻在摊位上;OpenWhisk 像“中央厨房”,用门铃、值班规则和流水线统一调度。本文就用这两类食堂模式,带你零基础看懂函数部署、事件触发、自动伸缩的差异,以及自己搭一套私有化云函数平台时该怎么选。
掌握两种主流自建 FaaS 平台的架构与取舍,能帮你在私有化 Serverless 选型时做出贴合团队与业务的决策,摆脱对公有云函数厂商的依赖,显著降低长期成本和数据合规风险。
可视化演示
展示OpenFaaS与OpenWhisk两大自建FaaS平台的核心机制:架构对比模式可视化五层架构差异(网关/队列/Worker/运行时/监控),函数伸缩模式展示基于流量的自动扩缩容与冷启动处理。
本节配有交互动效(进入视口后自动加载,约 3KB)。
OpenFaaS vs OpenWhisk架构 OpenFaaS: Gateway+NATS+K8s OpenWhisk: Controller+Kafka+DB 5层架构 请求→网关→队列→执行→监控
FaaS核心概念
你开了一家小饭馆,忙闲差异极大:午市挤爆、下午冷清。如果天天养十位固定厨师,闲时无事可做;如果只养两位,午市又忙不过来。于是你决定改成“按需食堂”——不养固定的灶台师傅,而是接到订单才临时叫厨师来做。这正是 Serverless / FaaS 的朴素原型:把“做菜的能力”租到云端,按单计费、用完即走。
落到技术上,FaaS(函数即服务)把这套“按需做菜”变成“按需执行代码”。开发者只需要写一个函数,声明“当某个事件发生时,跑这段逻辑”,剩下的运行环境、资源分配、扩缩容统统交给平台。就像你只管写菜谱,谁掌勺、用什么锅、忙时加几个人手,都交给“食堂管理员”。
FaaS 有三大特征:事件驱动(订单来了才开火)、免运维(不用自己囤菜备料)、按量计费(做一道收一道钱)。但“按需”也有代价——如果一道菜没人点,锅是冷的,突然来单就得先热锅,这个时间就是行业里常说的“冷启动”。
所以自建 FaaS 平台,本质就是你自己来当这位“食堂管理员”:既要保留按需做菜的灵活,又要亲自管好锅灶。接下来我们看两套现成的管理方案——OpenFaaS 和 OpenWhisk,它们分别对应“保温菜摊”和“中央厨房”两种经营哲学。
- 事件接入时间客户端请求到达平台入口所消耗的网络传输与协议解析时间,类似客人按门铃到门童开门的过程。
- 调度分配时间平台决定把请求交给哪个函数实例执行的开销,类似门童判断该叫哪位厨师。
- 冷启动时间当没有现成实例时,拉起新容器或新进程所需的时间,类似临时点火热锅的等待。
- 函数执行时间业务代码真正运行完成的时间,类似厨师真正掂勺炒菜的时间。
OpenFaaS架构
OpenFaaS 像“保温菜摊”模式。假设你已经有很多常备菜(函数),每道菜一口锅(容器),锅一直放在那边保温。客人点单后,前台(Gateway 网关)拿着单子走到对应摊位,锅口有个温度计兼传菜员(Watchdog),看到单子来了就把菜盛给客人。整个过程直白、可预期,客人不用等太久。
技术上的对应关系是:OpenFaaS 的核心组件是 Gateway 网关,它负责接收所有 HTTP 请求并按路由规则转发到对应函数;每个函数被打包成一个 Docker 镜像,容器内常驻一个叫 Watchdog 的小进程,它监听 HTTP 请求并把请求转交给你的函数进程执行。对使用者来说,函数怎么写都行,只要容器能起得来、Watchdog 能叫得动。
OpenFaaS 选择了“函数就是容器”的设计,底层对接 Kubernetes 或 Docker Swarm 来调度这些容器。因为函数本质是标准容器,团队已有的容器化经验、镜像仓库、Prometheus 监控体系都能直接复用。代价是每个函数至少占一个容器常驻,“锅必须一直热着”,空闲时也消耗资源。
保温菜摊的优势是直观、容易理解,和现有 Docker 技能无缝衔接;代价是“锅多耗气”,空闲成本高。如果你的团队天天和容器打交道,这套模式上手极快,几乎不需要额外学习新概念。
- 客户端发起请求用户的 HTTP 请求先到达 OpenFaaS 网关,这是所有流量的唯一入口。
- 网关路由转发Gateway 根据 URL 规则找到对应函数,把请求转发到该函数所在容器。
- 看门狗接管容器内的 Watchdog 进程监听请求,将其转为函数进程的输入并启动执行。
OpenWhisk架构
OpenWhisk 走的是“中央厨房调度”路线。它不设保温摊位,而是把做饭这件事拆成四件套:菜单(Action 动作)、门铃(Trigger 触发器)、值班规则(Rule 规则)和流水线(Sequence 序列)。客人按门铃,值班规则一看“按门铃 = 开始做菜”,就叫对应厨师按菜单执行;如果这道菜还有后续工序,流水线会自动衔接下一道。
技术映射:Action 是用户函数的最小执行单元,类似一道标准菜谱;Trigger 是事件来源的抽象,可以是 HTTP 请求、消息队列消息、定时器、对象存储变更等;Rule 把 Trigger 和 Action 绑定起来,形成“事件→规则→动作”的联动;Sequence 则把多个 Action 串成一条流水线,上一个动作的输出直接作为下一个动作的输入。
这套模型的核心收益是解耦:事件源、处理逻辑、触发条件各自独立变化。比如“订单消息到了”这个 Trigger,今天可以绑“发短信”动作,明天改绑“生成报表”动作,只需改规则,不必动代码。代价是概念比 OpenFaaS 多,入门门槛更高——中央厨房的规章制度总比菜摊多一些。
中央厨房适合“接单后还有多道工序”的复杂场景,但小饭馆想清楚再上——制度越多,学习成本越高。如果你的业务里充满了跨系统事件流转,这套模型的收益远大于学习成本。
- 触发器产生事件触发器代表某类事件来源,门铃响了但还不知道该叫谁。
- 规则绑定联动规则把触发器与特定动作关联起来,值班制度说“门铃响 = 找炒菜师傅”。
- 动作返回接力动作执行并返回结果,结果可作为新事件继续触发下一个动作。
部署流程对比
上新菜,两套厨房做法不同。保温菜摊要“连锅端来”:你得把菜(源码)和锅(Dockerfile)一起交给后厨(构建系统),烧好一口新锅摆在摊位(推送镜像),前台才能接单。中央厨房则省事些:只要把菜谱卡片(代码包 Zip)递进去,厨师看一眼就能照做,不用每次都准备锅。
技术对应:OpenFaaS 用 faas-cli 工具,通过 Dockerfile 把函数构建成 Docker 镜像,推送到镜像仓库,再由 Kubernetes 拉取调度。发布一个新函数往往需要几十秒到几分钟,因为镜像要构建、上传、拉取、启动。OpenWhisk 用 wsk 命令,把代码打包成 Zip 上传,平台用预置运行时(如 Node.js、Python、Java)直接创建 Action,几秒内即可完成。
这是一个明确的取舍:OpenFaaS 的“整锅上架”带来最大自由度——你可以在 Dockerfile 里装任何系统依赖、换任何基础镜像,甚至用冷门语言写函数;OpenWhisk 的“快速上新”则依赖预置运行时,只能选平台支持的语言版本,换语言版本或装特殊依赖都要走额外定制。
一句话:想要“什么都能做”选 OpenFaaS 的锅,想要“快速上新”选 OpenWhisk 的卡片式菜谱。实际项目中,如果发版频率高、函数数量多,部署速度的差异会直接影响研发效率。
- OpenFaaS 三步走构建镜像、推送仓库、K8s 拉取调度,每一步都要传输和等待大体积镜像。
- OpenWhisk 两步走打包代码并上传,平台用预置运行时缓存,秒级生效。
触发机制对比
客人怎么进店,两套厨房的思路也不同。保温菜摊基本是“客人上门”(HTTP 请求),另外请了几个“跑腿”(连接器)去外面拉客:比如定时拉客(Cron)、从消息队列入口接客(Kafka、钉钉等)。而中央厨房装了整套“门禁系统”:门铃(触发器)种类丰富,谁按门铃、该叫哪位厨师(规则)都写在值班制度里。
OpenFaaS 原生的触发方式以 HTTP 为主,其他事件(定时任务、消息队列、对象存储变更)需要额外部署 connector 或扩展组件,把外部事件转成 HTTP 请求打到网关。换句话说,OpenFaaS 是“被动等客 + 插件拉客”。OpenWhisk 则原生支持多种 Trigger feed(周期触发、消息触发、对象存储变更等),并能通过 Rule 把同一个事件同时分发给多个 Action,实现“一鱼多吃”。
从架构气质上看,OpenFaaS 更适合以 HTTP API 为核心的微服务场景;OpenWhisk 的 Trigger-Rule 模型则天生面向 Kafka、CouchDB、对象存储等异步事件源。如果业务大量依赖消息中间件联动,OpenWhisk 能省掉大量胶水代码。
类比收尾:如果一个食堂主要做堂食(HTTP),保温菜摊足够;如果还要做外卖、会员日短信、熟人带客等多种营销渠道(多事件源分流),中央厨房的规则系统更顺手。
- 事件源可以是 HTTP 请求、消息队列消息、定时器等任何外部事件生产者。
- 触发器汇聚OpenWhisk 把各种事件源统一包装成触发器,屏蔽来源差异。
- 规则分发规则匹配事件并决定它流向哪个动作,同一事件可发往多个动作。
- 链式接力动作结果可作为新事件继续触发下游动作,形成复杂事件链。
伸缩策略对比
吃饭高峰,两套厨房的加人策略截然不同。保温菜摊的老板习惯“看排队来算人手”:先观察几分钟热闹程度,确定确实忙不过来,才慢悠悠多开几口锅(阶梯式扩容);中央厨房则是“来一单派一人”:门铃一响,马上从待命厨师池里抓人去干,单多就立刻加人。
OpenFaaS 依托 Kubernetes HPA 与 Prometheus 指标做副本伸缩:持续采集请求数与 CPU 利用率,超过阈值就扩副本,回落后再缩副本,且受最小副本数保护——容器常驻为保温,所以几乎不会出现第一个请求要等冷启动的尴尬。OpenWhisk 的每个 Action 由 Invoker 实例池调度,按积压请求量即时分配实例,空闲时可以缩到零:最省资源,但冷启动频次高,突发时第一个请求可能要多等几百毫秒到几秒。
并发模型也有差异:OpenFaaS 的一个函数容器可以同时处理多个请求(靠 Watchdog 转给运行时可并发的进程),更像“一口锅同时炒几份菜”;OpenWhisk 的一个动作实例默认一次专注处理一个请求,更像“一位厨师同时只做一道菜”,并发靠多实例横向堆出来。
选型时想清楚:你的忙闲波动多大?能接受“来单先等热锅”吗?不能接受就选 OpenFaaS 的保温模式,能接受且想省资源就选 OpenWhisk 的零保温模式。
- 计算所需实例数按请求速率与单实例容量之比向上取整,得到满足负载至少需要多少实例。
- 下限保护与最小副本数取最大值,保证平台始终保留最低资源、避免频繁冷启动。
- 上限封顶与最大副本数取最小值,避免无限扩容打爆你的预算与集群资源。
选型决策建议
回到开篇的问题:我的食堂该选保温菜摊还是中央厨房?答案藏在你的现状里。如果团队已经深耕 Kubernetes 和 Docker,OpenFaaS 的学习曲线几乎为零,运维手段现成;如果业务大量依赖消息、定时器、对象存储做事件联动,OpenWhisk 的原生规则链会省掉许多自定义开发。
技术栈维度:绑定 Docker/K8s 生态的团队选 OpenFaaS,函数即容器、复用现有镜像体系;需要多语言运行时加复杂事件编排的团队选 OpenWhisk,内置 Trigger feed 和 Rule 引擎。社区维度:OpenFaaS 背靠 CNCF 生态,镜像生态丰富;OpenWhisk 是 Apache 顶级项目,在事件驱动领域模型更成熟。运维维度:OpenFaaS 组件更少、概念更少,小团队一周能上手;OpenWhisk 需要维护 Controller、Invoker、Kafka 等多个组件,适合有专职平台团队的场景。
一个实用的打分方法:分别评估两套平台在易用性、社区生态、伸缩能力、运维成本四个维度上的得分,再按权重加权求和,得分高者胜出。
最后给一句过来人的建议:小饭馆先开保温菜摊,把生意跑通;等订单变成多事件源、多工序的流水线,再考虑升级成中央厨房。平台不是越复杂越好,而是越匹配越好。
- 易用性权重最高上手快慢直接决定团队试错成本,占 35%。
- 生态打分社区活跃度、周边工具与文档丰富度,占 25%。
- 伸缩与运维各两成伸缩能力与运维成本旗鼓相当,各占 20%。
AI 应用场景
私有化部署内部工具函数平台
阶段:模型服务与工程落地(部署与推理服务)
解决的问题:公有云函数存在数据合规和成本失控风险——敏感数据出网不合规,调用峰值账单飙升。用 OpenFaaS 在公司内网搭一套“函数即服务”,把 AI 推理后的图片加水印、报表生成、审批回调等写成函数,数据全程不出内网,成本只跟实际调用量相关。
具体案例:某电商团队把“订单导出 PDF”做成 OpenFaaS 函数,前端下单后由 Gateway 同步调用;大促高峰时 HPA 自动从 1 个副本扩到 8 个,结束后自动缩回,整个平台跑在已有 K8s 集群上,零新增服务器。
事件驱动的 AI 数据处理管道
阶段:数据接入与预处理
解决的问题:传统定时脚本轮询对象存储,延迟高、链路难以维护;用 Apache OpenWhisk 的 Trigger-Rule-Action 把“文件上传→格式转码→AI 打标→结果通知”串成事件链,文件一落地就自动流转,无需值守。
具体案例:内容公司把视频上传事件接入 Trigger,Rule 分别绑定“转码”与“抽帧供 AI 分析”两个 Action,处理完成后通过 webhook 通知业务系统,全程无轮询、无人工干预。
混合双平台分工
阶段:系统架构设计
解决的问题:单一平台难以兼顾“简单 HTTP 服务”和“复杂事件编排”,可在同一集群里同时部署两套:OpenFaaS 承接同步 API 型函数,OpenWhisk 承接异步事件链,中间用消息队列解耦。
具体案例:某中台团队把实时查询类函数放 OpenFaaS,把“数据变更→清洗→入库→通知”放 OpenWhisk,两类负载各取所长,避免了“既要轻又要全”的纠结。
Python 演示
import mathimport random def simulate_load(days=30): """生成一段模拟的请求到达序列, 带波峰波谷""" random.seed(99) return [int(5 + 6 * math.sin(i / 6) ** 2 + random.randint(0, 5)) for i in range(days)] def scale_openfaas(loads, capacity=5, min_inst=1, max_inst=8): """OpenFaaS 风格: 指标窗口平滑 + 阶梯式扩缩容""" history, instances, pending = [], 1, 0 for rate in loads: pending += rate if pending > capacity * instances * 0.8 and instances < max_inst: instances += 1 elif pending < capacity * (instances - 1) * 0.3 and instances > min_inst: instances -= 1 pending = max(0, pending - capacity * instances) history.append(instances) return history def scale_openwhisk(loads, capacity=5, min_inst=1, max_inst=8): """OpenWhisk 风格: 按当前积压请求即时分配实例""" history, pending = [], 0 for rate in loads: pending += rate instances = max(min_inst, min(max_inst, math.ceil(pending / capacity))) pending = max(0, pending - capacity * instances) history.append(instances) return history def main(): loads = simulate_load() a = scale_openfaas(loads) b = scale_openwhisk(loads) print("时刻 请求 OpenFaaS实例 OpenWhisk实例") for i, (r, x, y) in enumerate(zip(loads, a, b)): print(f"{i:4d} {r:5d} {x:11d} {y:13d}") print("OpenFaaS实例总量:", sum(a)) print("OpenWhisk实例总量:", sum(b)) if __name__ == "__main__": main()
random.seed(99)固定随机种子,保证每次运行的请求序列一致,结果可复现。int(5 + 6 * math.sin(i / 6) ** 2 + random.randint(0, 5))生成带波峰波谷的模拟请求速率,模拟食堂午市高峰。if pending > capacity * instances * 0.8 and instances < max_inst:积压请求超过当前容量 80% 才加实例,体现 OpenFaaS 阶梯式慢伸缩。elif pending < capacity * (instances - 1) * 0.3 and instances > min_inst:积压大幅回落才减实例,避免频繁抖动。instances = max(min_inst, min(max_inst, math.ceil(pending / capacity)))按积压请求当场算出所需实例数,体现 OpenWhisk 即时分配。pending = max(0, pending - capacity * instances)扣减本轮已处理的请求量,剩下的继续积压。sum(a) / sum(b)统计两种策略的总实例数,用于对比资源占用。
常见误区
误区我看到 OpenFaaS 可以对接 Kafka、Cron,那它就是一个带事件触发的平台,事件编排能力和 OpenWhisk 应该是一样的。
正解OpenFaaS 的触发器大多是外部连接器(connector),本质是“拉”事件进来再转成 HTTP 请求打到网关;OpenWhisk 原生就有 Trigger/Rule/Action 三层事件模型,事件“推”进来后由规则自动分发。就像保温菜摊需要雇人外出去进货(connector),中央厨房本身就有收货台(feed)和分菜制度(rule),两者事件处理深度完全不同。
为何常见:只看功能列表会发现两者都能“事件驱动”,容易忽略原生支持与外部拼装的架构差异。
误区Serverless 就是免运维,自己搭一套 OpenFaaS 或 OpenWhisk 后,服务器就完全不用管了。
正解自建平台只是把“管服务器”从业务团队转移到平台团队,Kubernetes 集群、监控、存储、升级、补丁、安全漏洞照样要有人维护。相当于食堂不能开在真空中:买菜、煤气、消防、垃圾处理都得有人负责,只是食客(业务方)不操心了而已。
为何常见:"Serverless" 这个词的字面意思有很强的误导性,让人误以为完全没有服务器。
误区看文档里函数的例子都是 Go 和 Python,以为 OpenFaaS 只支持这两种语言。
正解OpenFaaS 的函数本质是任意 Docker 镜像里放一个能监听 HTTP 的进程(Watchdog),任何语言只要能起 HTTP 服务都能跑,Java、Node.js、Ruby,甚至 Bash 脚本都可以。锅是什么材质都能做菜,关键是锅里能装东西、锅口有人接单。
为何常见:从公有云厂商的运行时列表迁移到自建平台,容易惯性照搬语言限制。
误区OpenWhisk 是 IBM Cloud Functions 背后的引擎,应该是 IBM 的商业闭源产物,自建可能涉及授权问题。
正解OpenWhisk 是 Apache 软件基金会的顶级开源项目(Apache OpenWhisk),代码完全开源、可自由私有化部署,IBM 只是主要贡献者之一。它和 OpenFaaS 一样都是可以放心自建的开源 FaaS 框架。
为何常见:商业品牌与开源项目的强关联容易让人产生“闭源”的误判,就像很多人以为 Kubernetes 是 Google 的闭源产品一样。
面试题
Q1. OpenFaaS 中负责在函数容器内监听 HTTP 请求、并把请求转交给用户进程的组件是?
- A.Gateway 网关组件
- B.Watchdog 看门狗← 正确答案
- C.Prometheus 监控
- D.Kubernetes 集群
答案:B。Gateway 负责外部路由分发,Watchdog 才是在容器内部监听的“传菜员”;Prometheus 负责采集指标,K8s 负责调度容器。四者中只有 Watchdog 直接站在函数进程门口传话。
Q2. OpenWhisk 中 Trigger(触发器)的首要职责是?
- A.执行用户业务代码
- B.表示事件来源与发生← 正确答案
- C.把两个动作串联起来
- D.存储函数运行镜像
答案:B。Trigger 是事件来源的抽象,类似门铃——只负责“响了”这件事;真正执行代码的是 Action,串联动作的是 Sequence,存储镜像的不是触发器的职责。
Q3. 关于 OpenFaaS 的函数打包部署方式,以下哪项描述正确?
- A.用 faas-cli 构建 Docker 镜像← 正确答案
- B.只需上传一个 Zip 包即可
- C.不需要编写任何 Dockerfile
- D.必须使用 Go 语言编写函数
答案:A。OpenFaaS 的部署核心是 faas-cli + Dockerfile 构建镜像,因此要写 Dockerfile;OpenWhisk 才用 Zip 上传;语言方面任何能起 HTTP 服务的语言都可以。A 完全符合官方流程。
Q4. OpenWhisk 中 Rule(规则)的作用是?
- A.定义限流与熔断策略
- B.把触发器与动作关联起来← 正确答案
- C.设置函数伸缩的阈值
- D.管理平台的密钥凭证
答案:B。Rule 是值班制度,负责把“门铃响了”(Trigger)对应到“叫哪位厨师”(Action)。限流、伸缩阈值、密钥管理都不属于 Rule 的职责,它们由其他组件负责。
Q5. 相比公有云函数(如 AWS Lambda),自建 FaaS 平台的优势包括?
- A.数据保留在私有网络内← 正确答案
- B.运行环境完全自主控制← 正确答案
- C.平台完全免运维管理
- D.弹性能力完全不受限
答案:AB。自建平台最大的两个卖点就是数据不出内网和运行环境可控;但自建反而增加了运维负担,弹性上限也受自身集群资源约束,所以 C、D 描述恰恰相反。
Q6. OpenFaaS 的自动伸缩主要依赖哪个组件提供的指标?
- A.Prometheus 指标监控← 正确答案
- B.MySQL 数据库查询
- C.Redis 缓存读写带宽
- D.Nginx 反向代理日志
答案:A。OpenFaaS 通过 Prometheus 采集请求数、CPU 利用率等指标,再交给 Kubernetes HPA 做扩缩容决策。MySQL、Redis、Nginx 都不是它的指标来源。
Q7. OpenWhisk 中把多个动作串成一条流水线、上一个动作输出自动作为下一个动作输入的结构是?
- A.Sequence 动作序列← 正确答案
- B.Rule 事件规则
- C.Package 代码包
- D.Feed 事件源
答案:A。Sequence 就是中央厨房的流水线:做完成品自动传送到下一道工序。Rule 负责事件分发,Package 是代码组织单元,Feed 是事件源的接入器,都不具备流水线能力。
Q8. 关于自建 FaaS 平台的冷启动,以下说法正确的有?
- A.自建平台同样存在冷启动← 正确答案
- B.容器常驻可以显著减少冷启动← 正确答案
- C.OpenWhisk 可缩到零所以冷启动更频繁← 正确答案
- D.冷启动只与网络带宽有关
答案:ABC。冷启动是“热锅”时间,自建平台一样存在;OpenFaaS 容器常驻相当于锅一直热着,冷启动少;OpenWhisk 空闲缩到零,来单先热锅所以冷启动更频繁。冷启动主要与镜像拉取和进程启动有关,而非单纯网络带宽。
Q9. 团队已深度使用 Kubernetes,希望“函数就是普通容器”、复用现有镜像和监控体系,应优先选择?
- A.OpenFaaS 平台← 正确答案
- B.OpenWhisk 平台
- C.AWS Lambda 云函数
- D.自研一个网关组件
答案:A。OpenFaaS 的设计哲学就是“函数即容器”,直接跑在 K8s 上,复用镜像仓库、监控、调度;OpenWhisk 有自己的组件体系,与 K8s 关系较弱;Lambda 是公有云;自研网关成本太高且不划算。
Q10. 关于两平台的并发模型,理解正确的有?
- A.OpenFaaS 容器可同时处理多个请求← 正确答案
- B.OpenWhisk 一个实例同一时刻通常只处理一个请求← 正确答案
- C.两平台都支持按负载自动伸缩← 正确答案
- D.两平台并发模型完全相同
答案:ABC。OpenFaaS 像一口锅同时炒几份菜,一个容器可并发处理多请求;OpenWhisk 像一位厨师一次做一道菜,一个实例单请求,并发靠多实例堆;两者都支持自动伸缩。D 说完全相同是错的,这正是两平台的核心差异之一。