使用 Cloud Tasks 触发 Cloud Run 函数

本教程介绍如何在 App Engine 应用中使用 Cloud Tasks 触发 Cloud Run 函数并发送定时发送的邮件。

目标

  • 了解每个组件中的代码。
  • 创建一个 SendGrid 账号。
  • 下载源代码。
  • 部署 Cloud Run 函数,以接收 Cloud Tasks 请求并通过 SendGrid API 发送电子邮件。
  • 创建 Cloud Tasks 队列。
  • 创建服务账号以对您的 Cloud Tasks 请求进行身份验证。
  • 部署允许用户发送电子邮件的客户端代码。

费用

Cloud Tasks、Cloud Run 函数和 App Engine 具有免费层级,因此只要您在给定产品的免费层级中运行教程,就不会产生额外费用。如需了解详情,请参阅价格

准备工作

  1. 选择或创建 Google Cloud 项目。

    转到 App Engine 页面

  2. 在您的项目中初始化 App Engine 应用:

    1. 欢迎使用 App Engine网页点击创建应用

    2. 为您的应用选择一个区域。此位置将用作 Cloud Tasks 请求的 LOCATION_ID 参数,因此请记下该位置。请注意,App Engine 命令中名为 europe-west 和 us-central 的两个位置在 Cloud Tasks 命令中分别称为 europe-west1 和 us-central1。

    3. 选择 Node.js 作为语言,选择标准作为环境。

    4. 如果系统弹出启用结算窗口,请选择您的结算账号。如果您目前没有结算账号,请点击创建结算账号并按照向导中的说明操作。

    5. 开始页面,点击下一页。您稍后会处理此内容。

  3. 启用 Cloud Run 函数和 Cloud Tasks API。

    启用 API

  4. 安装并初始化 gcloud CLI

了解代码

此部分介绍了应用代码及其工作原理。

创建任务

索引页面使用 app.yaml 中的处理程序提供。创建任务所需的变量将作为环境变量传入。

runtime: nodejs16

env_variables:
  QUEUE_NAME: "my-queue"
  QUEUE_LOCATION: "us-central1"
  FUNCTION_URL: "https://<region>-<project_id>.cloudfunctions.net/sendEmail"
  SERVICE_ACCOUNT_EMAIL: "<member>@<project_id>.iam.gserviceaccount.com"

# Handlers for serving the index page.
handlers:
  - url: /static
    static_dir: static
  - url: /
    static_files: index.html
    upload: index.html

此代码会创建端点 /send-email。此端点会处理从索引页面提交的表单,并将该数据传递给任务创建代码。

app.post('/send-email', (req, res) => {
  // Set the task payload to the form submission.
  const {to_name, from_name, to_email, date} = req.body;
  const payload = {to_name, from_name, to_email};

  createHttpTaskWithToken(
    process.env.GOOGLE_CLOUD_PROJECT,
    QUEUE_NAME,
    QUEUE_LOCATION,
    FUNCTION_URL,
    SERVICE_ACCOUNT_EMAIL,
    payload,
    date
  );

  res.status(202).send('📫 Your postcard is in the mail! 💌');
});

此代码实际上会创建任务并将其发送到 Cloud Tasks 队列。代码通过以下方式构建任务:

  • 目标类型指定为 HTTP Request

  • 指定要使用的 HTTP method 和目标的 URL

  • Content-Type 标头设置为 application/json,以便下游应用可以解析结构化载荷。

  • 添加服务账号电子邮件,以便 Cloud Tasks 可以向请求目标提供凭据,这需要身份验证。此服务账号是单独创建的。

  • 检查以确保用户输入日期不超过 30 天,并将其作为字段 scheduleTime 添加到请求中。

const MAX_SCHEDULE_LIMIT = 30 * 60 * 60 * 24; // Represents 30 days in seconds.

const createHttpTaskWithToken = async function (
  project = 'my-project-id', // Your GCP Project id
  queue = 'my-queue', // Name of your Queue
  location = 'us-central1', // The GCP region of your queue
  url = 'https://example.com/taskhandler', // The full url path that the request will be sent to
  email = '<member>@<project-id>.iam.gserviceaccount.com', // Cloud IAM service account
  payload = 'Hello, World!', // The task HTTP request body
  date = new Date() // Intended date to schedule task
) {
  // Imports the Google Cloud Tasks library.
  const {v2beta3} = require('@google-cloud/tasks');

  // Instantiates a client.
  const client = new v2beta3.CloudTasksClient();

  // Construct the fully qualified queue name.
  const parent = client.queuePath(project, location, queue);

  // Convert message to buffer.
  const convertedPayload = JSON.stringify(payload);
  const body