函数计算(FaaS)快速上手:创建第一个函数、运行模式(事件触发/HTTP触发)、冷启动与并发、执行环境与生命周期
说到 Serverless,最核心的实操就是函数计算。我一向认为,光看文档不写代码,永远学不会。今天就带你亲手创建第一个函数,搞定两种触发模式,再聊聊冷启动和并发这些绕不开的坎。
1. 创建第一个函数:三步走
选一个平台,阿里云或 AWS Lambda 都行。我这里用阿里云 FC 举例,但逻辑通用。
- 新建服务和服务:在控制台创建一个服务(Service),名字随意。服务是函数的分组单元。
- 创建函数:选择“事件函数”类型,运行时选 Node.js 16 或 Python 3.9。代码直接写一个简单的 HTTP 响应。
- 部署并测试:控制台直接点测试,或绑一个 HTTP 触发器后访问 URL。
下面是一个最小可用的函数代码(Node.js):
// index.js
exports.handler = async (event, context, callback) => {
const body = JSON.parse(event.toString());
return {
statusCode: 200,
body: `Hello, ${body.name || 'World'}!`
};
};
部署后,你就能在日志里看到输出。我第一次跑通时,整整花了五分钟——不是因为代码难,而是忘了给角色授权。嗯,这里要注意:函数执行需要 RAM 角色 来访问日志、OSS 等其他服务,默认不配会报 403。
2. 运行模式:事件触发 vs HTTP 触发
函数计算支持两种主流触发方式,本质都是“事件驱动”,但使用场景差异很大。我做了个表格,帮你快速对比:
| 触发类型 | 典型场景 | 调用方式 | 响应要求 | 同步/异步 |
|---|---|---|---|---|
| 事件触发 | OSS 上传、定时任务、消息队列消费 | 平台自动投递事件 | 无返回(或回调) | 异步为主 |
| HTTP 触发 | API 网关、Webhook、前后端交互 | 外部 HTTP 请求 | 必须返回 HTTP 响应 | 同步 |
你想想看,如果你的函数需要对外提供 RESTful 接口,就用 HTTP 触发器;如果是后台处理文件或日志,就用事件触发。我曾经在一个项目中把 OSS 触发器错配成 HTTP,结果文件上传后函数没反应,排查了半天才发现触发器类型搞反了……
避坑指南:HTTP 触发器的函数必须显式设置超时时间,默认 3 秒,实际 API 网关转发还会有额外超时。我曾经遇到过一个处理图片压缩的函数,跑了 10 秒,结果网关直接 504。后来把超时调到 30 秒才解决。
3. 冷启动与并发:你躲不开的性能问题
冷启动,说白了就是函数实例第一次启动时,要加载代码、初始化运行环境、运行全局代码。这个过程通常在几百毫秒到几秒之间。为什么会有冷启动?因为平台为了节省资源,会在一段时间没有请求后销毁实例。
影响冷启动时长的几个关键因素:
- 运行时语言:Node.js 最快(<100ms),Python 和 Java 较慢(1-2s)。
- 代码包大小:每多 1MB,启动时间增加约 50-100ms。
- 依赖加载:npm install 或 pip install 的模块越多,启动越慢。
- VPC 配置:如果函数接入 VPC,每次冷启动需要额外花 1-3s 创建 ENI(弹性网卡)。
我记得有一次做日志巡检函数,每天凌晨跑一次,每次都等 3 秒的冷启动。后来我把函数预热方案加上去了——用一个定时触发器每 5 分钟调一次,保持实例热乎。你想想看,冷启动只在实例首次创建时发生,后续请求复用同一个实例,所以预热有用。
优化冷启动的常见手段:
- 预留并发(Reserved Concurrency):为关键函数预留固定数量的实例,避免冷启动。但要按量付费。
- 精简代码包:只打包必要依赖,使用打包工具(如 webpack、esbuild)做 tree-shaking。
- 使用轻量运行时:Node.js、Python 比 Java、.NET 快得多。
- 减少全局初始化:把数据库连接、HTTP 客户端声明在 handler 外部,只初始化一次。
4. 执行环境与生命周期
函数实例的生命周期分为三个阶段:初始化 → 调用 → 销毁。你可以理解为一个“微容器”。
- 初始化:平台拉取代码包、创建容器、执行全局代码(如 require 依赖、建立连接池)。这个阶段只做一次,除非实例被回收。
- 调用:每次事件或 HTTP 请求,平台都会调用你的 handler 函数。这个过程是并行的——同一个实例可以同时处理多个请求(并发),但注意代码必须是线程安全的。Node.js 单线程没问题,但 Python 要小心全局变量。
- 销毁:实例空闲超过阈值(一般 5-15 分钟,各平台不同),平台会停止容器。销毁前可能触发
Shutdown回调,可以用来优雅关闭连接。
执行环境的一些重要约束:
| 属性 | 典型值(以阿里云 FC 为例) | 说明 |
|---|---|---|
| 最大内存 | 3 GB(部分平台 10 GB) | 函数峰值使用不能超限 |
| 最大执行时长 | 600 秒(可申请提升) | 同步调用建议保持在 30s 内 |
| 临时磁盘空间 | 10 GB(/tmp) | 挂载后可读写,但实例销毁后数据丢失 |
| 并发实例数 | 默认 300(可提升) | 超过后请求会排队或降级 |
| 环境变量 | 大小 4 KB | 敏感信息建议用密钥管理 |
下图是我整理的一个 FaaS 核心概念关系图,帮你把这几块串起来:
总结一下:创建第一个函数最快只需 5 分钟,但真正理解冷启动与并发的相互关系需要实战。我建议你今晚就动手:先写一个最简单的 HTTP 函数,然后故意配一个很大的依赖包看看冷启动时间怎么变。嗯,这种“破坏性实验”往往比看书管用十倍。