GCP Cloud Functions:轻量无服务器事件驱动

FreeGuideOnline 最新 2026-06-30

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:事件唯一 ID
  • cloudEvent.source:事件来源(如存储桶资源名)
  • cloudEvent.type:事件类型
  • cloudEvent.data:负载数据,对于 Storage 事件,data 包含 bucketnamemetageneration 等字段

使用 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.jsondependencies
  • Python:requirements.txt
  • Go:go.mod 自动处理
  • Java:pom.xmlbuild.gradle

构建由 Cloud Build 完成。如果需要构建原生模块或有特殊构建步骤,可以添加一个构建配置文件 (.gcloudignore 排除不必要文件)。

调用与访问控制

  • HTTP 函数:支持公开(未认证)或需认证。若需认证,调用方必须传递有效的身份令牌或 OAuth 令牌。Cloud Scheduler、Workflows 等 GCP 服务默认拥有调用权限。
  • 事件驱动函数:通常由源服务(如 Storage)在事件发生时自动调用,无需额外的认证配置,权限由服务账号负责。

限制调用来源:可以在 Cloud Functions 触发条件中设置入口控制 (Ingress),选择“允许内部流量和 Cloud Load Balancing” 来增加安全性。

日志与监控

所有 console.logprint 等输出会自动发送到 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 查询...
});