GCP Cloud Functions:轻量无服务器事件驱动
javascript const functions = require('@google-cloud/functions-framework');
functions.http('helloWorld', (req, res) => {
const name = req.query.name || req.body.name || 'World';
res.status(200).send(Hello, ${name}!);
});
对应的 `package.json` 需要包含框架依赖(如果是 Node.js 第 2 代,会自动注入,但明确写出更佳):
```json
{
"dependencies": {
"@google-cloud/functions-framework": "^3.0.0"
}
}
点击 部署。部署过程会构建容器并部署,通常需要 1-3 分钟。
部署完成后,控制台会显示一个 HTTPS 端点 URL。在浏览器或终端访问该链接,你会看到 "Hello, World!"。加上 ?name=云函数 参数测试。
事件驱动函数:响应 Cloud Storage
让我们创建一个当文件上传到指定 Cloud Storage 存储桶时触发的函数。
步骤 1:创建存储桶触发器
在 Cloud Functions 创建页面,触发器类型选择 Cloud Storage。
- 事件类型:
google.cloud.storage.object.v1.finalized(文件创建完成) - 存储桶:选择或创建目标存储桶,例如
my-upload-bucket
注意:存储桶必须与函数位于同一区域,或使用默认区域桶。
步骤 2:编写处理代码
运行时仍选 Node.js 20。在代码编辑器中,index.js 内容:
const functions = require('@google-cloud/functions-framework');
functions.cloudEvent('handleFileUpload', async (cloudEvent) => {
const file = cloudEvent.data;
console.log(`检测到文件: ${file.bucket}/${file.name}`);
// 可以在这里添加处理逻辑:读取文件、转换格式、写入数据库等
});
package.json 依赖同样包含框架。
部署后,向该存储桶上传任意文件。进入 Cloud Functions 控制台,查看函数日志,你会看到打印的文件信息。
事件的上下文对象
在 CloudEvents 格式中(第 2 代统一采用 CloudEvents),事件对象包含:
cloudEvent.id:事件唯一 IDcloudEvent.source:事件来源(如存储桶资源名)cloudEvent.type:事件类型cloudEvent.data:负载数据,对于 Storage 事件,data包含bucket、name、metageneration等字段
使用 gcloud CLI 部署函数
在本地开发时,可以使用 gcloud 命令行工具。
安装并初始化 gcloud:
gcloud init
创建基本的 HTTP 函数目录结构:
my-function/
├── index.js
└── package.json
部署命令(第 2 代):
gcloud functions deploy my-http-function \
--gen2 \
--runtime=nodejs20 \
--region=us-central1 \
--source=. \
--entry-point=helloWorld \
--trigger-http \
--allow-unauthenticated
部署事件驱动函数(如 Cloud Storage):
gcloud functions deploy my-storage-function \
--gen2 \
--runtime=python310 \
--region=us-central1 \
--source=. \
--entry-point=handle_file_upload \
--trigger-event-filters="type=google.cloud.storage.object.v1.finalized" \
--trigger-event-filters="bucket=my-upload-bucket"
多语言示例
Python HTTP 函数
main.py:
import functions_framework
@functions_framework.http
def hello_http(request):
request_json = request.get_json(silent=True)
name = request_json.get('name') if request_json else request.args.get('name', 'World')
return f'Hello, {name}!'
requirements.txt:
functions-framework==3.*
Go HTTP 函数
go.mod 引入模块,function.go:
package myfunction
import (
"fmt"
"net/http"
"github.com/GoogleCloudPlatform/functions-framework-go/functions"
)
func init() {
functions.HTTP("HelloWorld", helloWorld)
}
func helloWorld(w http.ResponseWriter, r *http.Request) {
name := r.URL.Query().Get("name")
if name == "" {
name = "World"
}
fmt.Fprintf(w, "Hello, %s!", name)
}
环境变量与配置
函数运行时可以通过环境变量注入配置,避免将密钥硬编码在代码中。
部署时设置环境变量(命令行):
gcloud functions deploy my-func \
--set-env-vars=API_KEY=your-api-key,ENV=production
在控制台部署时,展开“运行时、构建和连接” → “环境变量”即可添加。
代码中读取(Node.js):
const apiKey = process.env.API_KEY;
(Python):os.environ.get('API_KEY')
依赖管理
函数在部署时会根据语言规范安装依赖:
- Node.js:
package.json的dependencies - Python:
requirements.txt - Go:
go.mod自动处理 - Java:
pom.xml或build.gradle
构建由 Cloud Build 完成。如果需要构建原生模块或有特殊构建步骤,可以添加一个构建配置文件 (.gcloudignore 排除不必要文件)。
调用与访问控制
- HTTP 函数:支持公开(未认证)或需认证。若需认证,调用方必须传递有效的身份令牌或 OAuth 令牌。Cloud Scheduler、Workflows 等 GCP 服务默认拥有调用权限。
- 事件驱动函数:通常由源服务(如 Storage)在事件发生时自动调用,无需额外的认证配置,权限由服务账号负责。
限制调用来源:可以在 Cloud Functions 触发条件中设置入口控制 (Ingress),选择“允许内部流量和 Cloud Load Balancing” 来增加安全性。
日志与监控
所有 console.log、print 等输出会自动发送到 Cloud Logging。在控制台函数的“日志”选项卡即可查看实时日志和错误堆栈。
监控指标(如调用次数、执行时间、内存使用)自动集成到 Cloud Monitoring,你可以设置基于错误的提醒。
建议在代码中加入结构化日志,方便搜索:
console.log(JSON.stringify({severity: 'INFO', message: 'Processing image', file: fileName}));
错误处理与重试
对于事件驱动函数,如果函数返回错误(非 2xx 响应),Eventarc 默认会进行重试。你可以配置重试策略:
- 第 2 代函数:在创建时,在事件触发部分可勾选“失败时重试”。
- 最大重试持续时间默认为7天(根据事件源可能受限)。
确保函数具有幂等性,因为事件可能至少投递一次。
性能调优建议
- 合理分配内存:内存越大,CPU 能力越强。从 128 MiB 起步,根据函数实际 CPU 使用率和延迟调整。
- 设置最小实例数(第 2 代):可以为时延敏感的函数配置最小实例,避免冷启动。注意会产生空闲实例费用。
- 使用全局变量存放外部连接:在函数实例生命周期内复用数据库连接、库客户端等。对于 Node.js,初始化放在全局作用域,不在函数体内:
const {BigQuery} = require('@google-cloud/bigquery');
const bigquery = new BigQuery(); // 复用该对象
functions.http('myfunc', async (req, res) => {
// 使用 bigquery 查询...
});