创建 HTTP 目标任务

Cloud Tasks 处理程序可以在具有外部 IP 地址的任何 HTTP 端点(例如 GKECompute Engine,甚至是本地 Web 服务器)上运行。您可以以可靠且可配置的方式对其中任一服务执行您的任务。

本页面演示了如何以编程方式创建基本 HTTP 目标任务并将其置于 Cloud Tasks 队列中。

对于具有 HTTP 目标(而不是不常见的明确 App Engine 目标)的任务,可以通过以下两种方式创建任务:

  • BufferTask 方法:如果您的队列设置为在服务前缓冲任务,请使用此方法。队列必须具有队列级路由。 对于大多数使用场景,这是最好的方法。此方法使用 BufferTask 方法。

  • CreateTask 方法:该方法较复杂。您必须明确创建一个任务对象。如果队列中的任务具有不同的路由配置,请使用此方法。在这种情况下,您需要在任务级别指定路由,并且无法使用队列级别路由。此方法使用 CreateTask 方法。

创建基本任务(BufferTask 方法)

本部分介绍如何通过发送 HTTP 请求来创建任务。您使用的方法称为 BufferTask

限制

BufferTask 方法受到以下限制:

  • 客户端库:客户端库不支持 BufferTask 方法。

  • RPC API:RPC API 不支持 BufferTask 方法。

  • 任务级别路由:此方法不支持任务级别路由。由于以这种方式创建任务时没有地方添加路由信息,因此您必须使用队列级路由(否则,任务没有路由信息)。如果您的队列尚未使用队列级别路由,请参阅为 HTTP 任务配置队列级别路由

调用 BufferTask 方法

以下示例展示了如何通过向 Cloud Tasks API buffer 端点发送 HTTP POST 请求来创建任务。

Python

from google.cloud import tasks_v2beta3 as tasks

import requests


def send_task_to_http_queue(
    queue: tasks.Queue, body: str = "", token: str = "", headers: dict = {}
) -> int:
    """Send a task to an HTTP queue.
    Args:
        queue: The queue to delete.
        body: The body of the task.
        auth_token: An authorization token for the queue.
        headers: Headers to set on the task.
    Returns:
        The matching queue, or None if it does not exist.
    """

    # Use application default credentials if not supplied in a header
    if token:
        headers["Authorization"] = f"Bearer {token}"

    endpoint = f"https://cloudtasks.googleapis.com/v2beta3/{queue.name}/tasks:buffer"
    response = requests.post(endpoint, body, headers=headers)

    return response.status_code

curl

以下代码段举例说明了如何使用 BufferTask 方法和 curl 创建任务:

curl -X HTTP_METHOD\
"https://cloudtasks.googleapis.com/v2/projects/PROJECT_ID/locations/LOCATION/queues/QUEUE_ID/tasks:buffer" \

请替换以下内容:

  • HTTP_METHOD:请求的 HTTP 方法,例如 GETPOST
  • PROJECT_ID:您的 Google Cloud 项目的 ID。您可以在终端中运行以下命令来获取此信息:
    gcloud config get-value project
  • LOCATION:您的队列位置。
  • QUEUE_ID:队列的 ID。

高级任务创建(CreateTask 方法)

本部分介绍如何通过构造任务对象来创建任务。您可以使用 CreateTask 方法。

使用 CreateTask 方法创建任务时,您可以明确创建和定义任务对象。您必须指定用于处理任务的服务和处理程序。

您可以选择将特定于任务的数据传递给处理程序。您还可以微调任务的配置,例如安排在未来某个时间执行该任务,或限制您希望在任务失败时重试的次数(请参阅高级配置)。

以下示例会调用 CreateTask 方法,以使用 Cloud Tasks 客户端库创建任务。

C#


using Google.Cloud.Tasks.V2;
using Google.Protobuf;
using Google.Protobuf.WellKnownTypes;
using System;

class CreateHttpTask
{
    public string CreateTask(
        string projectId = "YOUR-PROJECT-ID",
        string location = "us-central1",
        string queue = "my-queue",
        string url = "http://example.com/taskhandler",
        string payload = "Hello World!",
        int inSeconds = 0)
    {
        CloudTasksClient client = CloudTasksClient.Create();
        QueueName parent = new QueueName(projectId, location, queue);

        var response = client.CreateTask(new CreateTaskRequest
        {
            Parent = parent.ToString(),
            Task = new Task
            {
                HttpRequest = new HttpRequest
                {
                    HttpMethod = HttpMethod.Post,
                    Url = url,
                    Body = ByteString.CopyFromUtf8(payload)
                },
                ScheduleTime = Timestamp.FromDateTime(
                    DateTime.UtcNow.AddSeconds(inSeconds))
            }
        });

        Console.WriteLine($"Created Task {response.Name}");
        return response.Name;
    }
}

Python

import datetime
import json
from typing import Dict, Optional

from google.cloud import tasks_v2
from google.protobuf import duration_pb2, timestamp_pb2


def create_http_task(
    project: str,
    location: str,
    queue: str,
    url: str,
    json_payload: Dict,
    scheduled_seconds_from_now: Optional[int] = None,
    task_id: Optional[str] = None,
    deadline_in_seconds: Optional[int] = None,
) -> tasks_v2.Task:
    """Create an HTTP POST task with a JSON payload.
    Args:
        project: The project ID where the queue is located.
        location: The location where the queue is located.
        queue: The ID of the queue to add the task to.
        url: The target URL of the task.
        json_payload: The JSON payload to send.
        scheduled_seconds_from_now: Seconds from now to schedule the task for.
        task_id: ID to use for the newly created task.
        deadline_in_seconds: The deadline in seconds for task.
    Returns:
        The newly created task.
    """

    # Create a client.
    client = tasks_v2.CloudTasksClient()

    # Construct the task.
    task = tasks_v2.Task(
        http_request=tasks_v2.HttpRequest(
            http_method=tasks_v2.HttpMethod.POST,
            url=url,
            headers={"Content-type": "application/json"},
            body=json.dumps(json_payload).encode(),
        ),
        name=(
            client.task_path(project, location, queue, task_id)
            if task_id is not None
            else None
        ),
    )

    # Convert "seconds from now" to an absolute Protobuf Timestamp
    if scheduled_seconds_from_now is not None:
        timestamp = timestamp_pb2.Timestamp()
        timestamp.FromDatetime(
            datetime.datetime.utcnow()
            + datetime.timedelta(seconds=scheduled_seconds_from_now)
        )
        task.schedule_time = timestamp

    # Convert "deadline in seconds" to a Protobuf Duration
    if deadline_in_seconds is not None:
        duration = duration_pb2.Duration()
        duration.FromSeconds(deadline_in_seconds)
        task.dispatch_deadline = duration

    # Use the client to send a CreateTaskRequest.
    return client.create_task(
        tasks_v2.CreateTaskRequest(
            # The queue to add the task to
            parent=client.queue_path(project, location, queue),
            # The task itself
            task=task,
        )
    )

请注意 requirements.txt 文件:

google-cloud-tasks==2.13.1

Java

import com.google.cloud.tasks.v2.CloudTasksClient;
import com.google.cloud.tasks.v2.HttpMethod;
import com.google.cloud.tasks.v2.HttpRequest;
import com.google.cloud.tasks.v2.QueueName;
import com.google.cloud.tasks.v2.Task;
import com.google.protobuf.ByteString;
import java.io.IOException;
import java.nio.charset.Charset;

public class CreateHttpTask {

  public static void main(String[] args) throws IOException {
    // TODO(developer): Replace these variables before running the sample.
    String projectId = "my-project-id";
    String locationId = "us-central1";
    String queueId = "my-queue";
    createTask(projectId, locationId, queueId);
  }

  // Create a task with a HTTP target using the Cloud Tasks client.
  public static void createTask(String projectId, String locationId, String queueId)
      throws IOException {

    // Instantiates a client.
    try (CloudTasksClient client = CloudTasksClient.create()) {
      String url = "https://example.com/taskhandler";
      String payload = "Hello, World!";

      // Construct the fully qualified queue name.
      String queuePath = QueueName.of(projectId, locationId, queueId).toString();

      // Construct the task body.
      Task.Builder taskBuilder =
          Task.newBuilder()
              .setHttpRequest(
                  HttpRequest.newBuilder()
                      .setBody(ByteString.copyFrom(payload, Charset.defaultCharset()))
                      .setUrl(url)
                      .setHttpMethod(HttpMethod.POST)
                      .build());

      // Send create task request.
      Task task = client.createTask(queuePath, taskBuilder.build());
      System.out.println("Task created: " + task.getName());
    }
  }
}

请注意 pom.xml 文件:

<?xml version='1.0' encoding='UTF-8'?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example.tasks</groupId>
  <artifactId>cloudtasks-snippets</artifactId>
  <packaging>jar</packaging>
  <name>Google Cloud Tasks Snippets</name>

  <!--
    The parent pom defines common style checks and testing strategies for our samples.
    Removing or replacing it should not affect the execution of the samples in anyway.
  -->
  <parent>
    <groupId>com.google.cloud.samples</groupId>
    <artifactId>shared-configuration</artifactId>
    <version>1.2.0</version>
  </parent>

  <properties>
    <maven.compiler.target>1.8</maven.compiler.target>
    <maven.compiler.source>1.8</maven.compiler.source>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>


  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>com.google.cloud</groupId>
        <artifactId>libraries-bom</artifactId>
        <version>26.32.0</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>

  <dependencies>
    <dependency>
      <groupId>com.google.cloud</groupId>
      <artifactId>google-cloud-tasks</artifactId>
    </dependency>

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13.2</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>com.google.truth</groupId>
      <artifactId>truth</artifactId>
      <version>1.4.0</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

PHP

use Google\Cloud\Tasks\V2\Client\CloudTasksClient;
use Google\Cloud\Tasks\V2\CreateTaskRequest;
use Google\Cloud\Tasks\V2\HttpMethod;
use Google\Cloud\Tasks\V2\HttpRequest;
use Google\Cloud\Tasks\V2\Task;

/** Uncomment and populate these variables in your code */
// $projectId = 'The Google project ID';
// $locationId = 'The Location ID';
// $queueId = 'The Cloud Tasks Queue ID';
// $url = 'The full url path that the task request will be sent to.'
// $payload = 'The payload your task should carry to the task handler. Optional';

// Instantiate the client and queue name.
$client = new CloudTasksClient();
$queueName = $client->queueName($projectId, $locationId, $queueId);

// Create an Http Request Object.
$httpRequest = new HttpRequest();
// The full url path that the task request will be sent to.
$httpRequest->setUrl($url);
// POST is the default HTTP method, but any HTTP method can be used.
$httpRequest->setHttpMethod(HttpMethod::POST);
// Setting a body value is only compatible with HTTP POST and PUT requests.
if (!empty($payload)) {
    $httpRequest->setBody($payload);
}

// Create a Cloud Task object.
$task = new Task();
$task->setHttpRequest($httpRequest);

// Send request and print the task name.
$request = (new CreateTaskRequest())
    ->setParent($queueName)
    ->setTask($task);
$response = $client->createTask($request);
printf('Created task %s' . PHP_EOL, $response->getName());

请注意 composer.json 文件:

{
    "require": {
        "google/cloud-tasks": "^1.14"
    }
}

Go


// Command createHTTPtask constructs and adds a task to a Cloud Tasks Queue.
package main

import (
	"context"
	"fmt"

	cloudtasks "cloud.google.com/go/cloudtasks/apiv2"
	taskspb "cloud.google.com/go/cloudtasks/apiv2/cloudtaskspb"
)

// createHTTPTask creates a new task with a HTTP target then adds it to a Queue.
func createHTTPTask(projectID, locationID, queueID, url, message string) (*taskspb.Task, error) {

	// Create a new Cloud Tasks client instance.
	// See https://godoc.org/cloud.google.com/go/cloudtasks/apiv2
	ctx := context.Background()
	client, err := cloudtasks.NewClient(ctx)
	if err != nil {
		return nil, fmt.Errorf("NewClient: %w", err)
	}
	defer client.Close()

	// Build the Task queue path.
	queuePath := fmt.Sprintf("projects/%s/locations/%s/queues/%s", projectID, locationID, queueID)

	// Build the Task payload.
	// https://godoc.org/google.golang.org/genproto/googleapis/cloud/tasks/v2#CreateTaskRequest
	req := &taskspb.CreateTaskRequest{
		Parent: queuePath,
		Task: &taskspb.Task{
			// https://godoc.org/google.golang.org/genproto/googleapis/cloud/tasks/v2#HttpRequest
			MessageType: &taskspb.Task_HttpRequest{
				HttpRequest: &taskspb.HttpRequest{
					HttpMethod: taskspb.HttpMethod_POST,
					Url:        url,
				},
			},
		},
	}

	// Add a payload message if one is present.
	req.Task.GetHttpRequest().Body = []byte(message)

	createdTask, err := client.CreateTask(ctx, req)
	if err != nil {
		return nil, fmt.Errorf("cloudtasks.CreateTask: %w", err)
	}

	return createdTask, nil
}

Node.js

// Imports the Google Cloud Tasks library.
const {CloudTasksClient} = require('@google-cloud/tasks');

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

async function createHttpTask() {
  // TODO(developer): Uncomment these lines and replace with your values.
  // const project = 'my-project-id';
  // const queue = 'my-queue';
  // const location = 'us-central1';
  // const url = 'https://example.com/taskhandler';
  // const payload = 'Hello, World!';
  // const inSeconds = 180;

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

  const task = {
    httpRequest: {
      headers: {
        'Content-Type': 'text/plain', // Set content type to ensure compatibility your application's request parsing
      },
      httpMethod: 'POST',
      url,
    },
  };

  if (payload) {
    task.httpRequest.body = Buffer.from(payload).toString('base64');
  }

  if (inSeconds) {
    // The time when the task is scheduled to be attempted.
    task.scheduleTime = {
      seconds: parseInt(inSeconds) + Date.now() / 1000,
    };
  }

  // Send create task request.
  console.log('Sending task:');
  console.log(task);
  const request = {parent: parent, task: task};
  const [response] = await client.createTask(request);
  console.log(`Created task ${response.name}`);
}
createHttpTask();

请注意 package.json 文件:

{
  "name": "appengine-cloudtasks",
  "description": "Google App Engine Cloud Tasks example.",
  "license": "Apache-2.0",
  "author": "Google Inc.",
  "private": true,
  "engines": {
    "node": ">=16.0.0"
  },
  "files": [
    "*.js"
  ],
  "scripts": {
    "test": "c8 mocha -p -j 2 --timeout 30000",
    "start": "node server.js"
  },
  "dependencies": {
    "@google-cloud/tasks": "^4.0.0",
    "express": "^4.16.3"
  },
  "devDependencies": {
    "c8": "^8.0.0",
    "chai": "^4.2.0",
    "mocha": "^10.0.0",
    "uuid": "^9.0.0"
  }
}

Ruby

require "google/cloud/tasks"

# Create a Task with an HTTP Target
#
# @param [String] project_id Your Google Cloud Project ID.
# @param [String] location_id Your Google Cloud Project Location ID.
# @param [String] queue_id Your Google Cloud Tasks Queue ID.
# @param [String] url The full path to sent the task request to.
# @param [String] payload The request body of your task.
# @param [Integer] seconds The delay, in seconds, to process your task.
def create_http_task project_id, location_id, queue_id, url, payload: nil, seconds: nil
  # Instantiates a client.
  client = Google::Cloud::Tasks.cloud_tasks

  # Construct the fully qualified queue name.
  parent = client.queue_path project: project_id, location: location_id, queue: queue_id

  # Construct task.
  task = {
    http_request: {
      http_method: "POST",
      url:         url
    }
  }

  # Add payload to task body.
  task[:http_request][:body] = payload if payload

  # Add scheduled time to task.
  if seconds
    timestamp = Google::Protobuf::Timestamp.new
    timestamp.seconds = Time.now.to_i + seconds.to_i
    task[:schedule_time] = timestamp
  end

  # Send create task request.
  puts "Sending task #{task}"

  response = client.create_task parent: parent, task: task

  puts "Created task #{response.name}" if response.name
end

为 HTTP 目标处理程序身份验证设置服务帐号

如果您的服务帐号具有访问 HTTP 目标处理程序所需的相应凭据,则 Cloud Tasks 可以调用该处理程序。

如果您想使用当前的服务账号,则。只需为其授予适当的角色即可。这些说明涵盖了专门为此函数新创建的服务账号。 用于 Cloud Tasks 身份验证的现有服务账号或新服务账号必须与 Cloud Tasks 队列位于同一项目中。

  1. 在 Google Cloud 控制台中,转到服务账号页面。

    转到“服务账号”

  2. 如有必要,请选择适当的项目。

  3. 点击创建服务账号

  4. 服务帐号详情部分,为帐号命名。控制台会为该帐号创建一个相关的电子邮件帐号名称。这是您引用该帐号的方式。您还可以添加帐号用途的说明。点击创建并继续

  5. 向此服务帐号授予对项目的访问权限部分中,点击选择角色。搜索并选择 Cloud Tasks Enqueuer。 此角色可向服务帐号授予将任务添加到队列的权限。

  6. 点击 + 添加其他角色

  7. 点击选择角色 搜索并选择 Service Account User(服务帐号用户)。此角色允许服务帐号授权队列使用服务帐号的凭据代表其创建令牌。

  8. 如果您的处理程序是 Google Cloud 的一部分,请向服务账号授予一个角色,并且该角色与在处理程序运行时访问的服务相关联。 Google Cloud 中的每项服务都需要不同的角色。例如,要访问 Cloud Run 上的处理程序,需要Cloud Run Invoker角色,以此类推。您可以使用刚刚创建的服务账号或项目中的任何其他服务账号。

  9. 点击完成以完成服务账号的创建。

Cloud Tasks 本身必须拥有自己的服务账号,且该账号已获得 Cloud Tasks Service Agent 角色。这样,它就可以根据与 Cloud Tasks 服务账号关联的凭据生成标头令牌,然后向处理程序目标进行身份验证。在您启用 Cloud Tasks API 时,系统会自动创建 Cloud Tasks 服务账号并授予此角色,除非您已在 2019 年 3 月 19 日之前启用此功能,在这种情况下,您必须手动添加此角色

将 HTTP 目标任务与身份验证令牌搭配使用

为了在 Cloud Tasks 和需要此类身份验证的 HTTP 目标处理程序之间进行身份验证,Cloud Tasks 会创建一个标头令牌。此令牌是基于 Cloud Tasks Enqueuer 服务账号的凭据,其标识为该电子邮件地址 用于身份验证的服务帐号必须属于您的 Cloud Tasks 队列所在项目。带有标头令牌的请求通过 HTTPS 从队列发送到处理程序。您可以使用 ID 令牌访问令牌。ID 令牌通常用于在 Google Cloud 上运行的任何处理程序,例如在 Cloud Functions 或 Cloud Run 上运行。主要的例外情况是托管在 *.googleapis.com 上的 Google API:这些 API 需要访问令牌。

您可以在队列级别或任务级别配置身份验证。如需在队列级别配置身份验证,请参阅创建 Cloud Tasks 队列。如果在队列级别配置了身份验证,则此配置将替换任务级别的配置。如需在任务级别配置身份验证,请在任务本身中指定 ID (OIDC) 令牌访问 (OAuth) 令牌

BufferTask 方法

在使用 BufferTask 方法创建任务时,以下示例使用应用默认凭据进行身份验证。

Python

在以下代码示例中,请提供您的身份验证令牌值。

from google.cloud import tasks_v2beta3 as tasks

import requests


def send_task_to_http_queue(
    queue: tasks.Queue, body: str = "", token: str = "", headers: dict = {}
) -> int:
    """Send a task to an HTTP queue.
    Args:
        queue: The queue to delete.
        body: The body of the task.
        auth_token: An authorization token for the queue.
        headers: Headers to set on the task.
    Returns:
        The matching queue, or None if it does not exist.
    """

    # Use application default credentials if not supplied in a header
    if token:
        headers["Authorization"] = f"Bearer {token}"

    endpoint = f"https://cloudtasks.googleapis.com/v2beta3/{queue.name}/tasks:buffer"
    response = requests.post(endpoint, body, headers=headers)

    return response.status_code

curl

curl -X HTTP_METHOD\
"https://cloudtasks.googleapis.com/v2/projects/PROJECT_ID/locations/LOCATION/queues/QUEUE_ID/tasks:buffer" \
    -H "Authorization: Bearer ACCESS_TOKEN"

请替换以下内容:

  • HTTP_METHOD:请求的 HTTP 方法,例如 GETPOST
  • PROJECT_ID:您的 Google Cloud 项目的 ID。您可以在终端中运行以下命令来获取此信息:
    gcloud config get-value project
  • LOCATION:您的队列位置。
  • QUEUE_ID:队列的 ID。
  • ACCESS_TOKEN:您的访问令牌。您可以通过在终端运行以下命令来获取此信息:
  • gcloud auth application-default login
  • gcloud auth application-default print-access-token

CreateTask 方法

以下示例将 CreateTask 方法与 Cloud Tasks 客户端库结合使用来创建一项任务,该任务还包括创建标头令牌的操作。示例中使用的是 ID 令牌。 如需使用访问令牌,请在构建请求时将 OIDC 参数替换为相应语言的 OAuth 参数。

Python

from typing import Optional

from google.cloud import tasks_v2


def create_http_task_with_token(
    project: str,
    location: str,
    queue: str,
    url: str,
    payload: bytes,
    service_account_email: str,
    audience: Optional[str] = None,
) -> tasks_v2.Task:
    """Create an HTTP POST task with an OIDC token and an arbitrary payload.
    Args:
        project: The project ID where the queue is located.
        location: The location where the queue is located.
        queue: The ID of the queue to add the task to.
        url: The target URL of the task.
        payload: The payload to send.
        service_account_email: The service account to use for generating the OIDC token.
        audience: Audience to use when generating the OIDC token.
    Returns:
        The newly created task.
    """

    # Create a client.
    client = tasks_v2.CloudTasksClient()

    # Construct the request body.
    task = tasks_v2.Task(
        http_request=tasks_v2.HttpRequest(
            http_method=tasks_v2.HttpMethod.POST,
            url=url,
            oidc_token=tasks_v2.OidcToken(
                service_account_email=service_account_email,
                audience=audience,
            ),
            body=payload,
        ),
    )

    # Use the client to build and send the task.
    return client.create_task(
        tasks_v2.CreateTaskRequest(
            parent=client.queue_path(project, location, queue),
            task=task,
        )
    )

请注意 requirements.txt 文件:

google-cloud-tasks==2.13.1

Java

import com.google.cloud.tasks.v2.CloudTasksClient;
import com.google.cloud.tasks.v2.HttpMethod;
import com.google.cloud.tasks.v2.HttpRequest;
import com.google.cloud.tasks.v2.OidcToken;
import com.google.cloud.tasks.v2.QueueName;
import com.google.cloud.tasks.v2.Task;
import com.google.protobuf.ByteString;
import java.io.IOException;
import java.nio.charset.Charset;

public class CreateHttpTaskWithToken {

  public static void main(String[] args) throws IOException {
    // TODO(developer): Replace these variables before running the sample.
    String projectId = "my-project-id";
    String locationId = "us-central1";
    String queueId = "my-queue";
    String serviceAccountEmail =
        "java-docs-samples-testing@java-docs-samples-testing.iam.gserviceaccount.com";
    createTask(projectId, locationId, queueId, serviceAccountEmail);
  }

  // Create a task with a HTTP target and authorization token using the Cloud Tasks client.
  public static void createTask(
      String projectId, String locationId, String queueId, String serviceAccountEmail)
      throws IOException {

    // Instantiates a client.
    try (CloudTasksClient client = CloudTasksClient.create()) {
      String url =
          "https://example.com/taskhandler"; // The full url path that the request will be sent to
      String payload = "Hello, World!"; // The task HTTP request body

      // Construct the fully qualified queue name.
      String queuePath = QueueName.of(projectId, locationId, queueId).toString();

      // Add your service account email to construct the OIDC token.
      // in order to add an authentication header to the request.
      OidcToken.Builder oidcTokenBuilder =
          OidcToken.newBuilder().setServiceAccountEmail(serviceAccountEmail);

      // Construct the task body.
      Task.Builder taskBuilder =
          Task.newBuilder()
              .setHttpRequest(
                  HttpRequest.newBuilder()
                      .setBody(ByteString.copyFrom(payload, Charset.defaultCharset()))
                      .setHttpMethod(HttpMethod.POST)
                      .setUrl(url)
                      .setOidcToken(oidcTokenBuilder)
                      .build());

      // Send create task request.
      Task task = client.createTask(queuePath, taskBuilder.build());
      System.out.println("Task created: " + task.getName());
    }
  }
}

请注意 pom.xml 文件:

<?xml version='1.0' encoding='UTF-8'?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example.tasks</groupId>
  <artifactId>cloudtasks-snippets</artifactId>
  <packaging>jar</packaging>
  <name>Google Cloud Tasks Snippets</name>

  <!--
    The parent pom defines common style checks and testing strategies for our samples.
    Removing or replacing it should not affect the execution of the samples in anyway.
  -->
  <parent>
    <groupId>com.google.cloud.samples</groupId>
    <artifactId>shared-configuration</artifactId>
    <version>1.2.0</version>
  </parent>

  <properties>
    <maven.compiler.target>1.8</maven.compiler.target>
    <maven.compiler.source>1.8</maven.compiler.source>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>


  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>com.google.cloud</groupId>
        <artifactId>libraries-bom</artifactId>
        <version>26.32.0</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>

  <dependencies>
    <dependency>
      <groupId>com.google.cloud</groupId>
      <artifactId>google-cloud-tasks</artifactId>
    </dependency>

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13.2</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>com.google.truth</groupId>
      <artifactId>truth</artifactId>
      <version>1.4.0</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

Go

import (
	"context"
	"fmt"

	cloudtasks "cloud.google.com/go/cloudtasks/apiv2"
	taskspb "cloud.google.com/go/cloudtasks/apiv2/cloudtaskspb"
)

// createHTTPTaskWithToken constructs a task with a authorization token
// and HTTP target then adds it to a Queue.
func createHTTPTaskWithToken(projectID, locationID, queueID, url, email, message string) (*taskspb.Task, error) {
	// Create a new Cloud Tasks client instance.
	// See https://godoc.org/cloud.google.com/go/cloudtasks/apiv2
	ctx := context.Background()
	client, err := cloudtasks.NewClient(ctx)
	if err != nil {
		return nil, fmt.Errorf("NewClient: %w", err)
	}
	defer client.Close()

	// Build the Task queue path.
	queuePath := fmt.Sprintf("projects/%s/locations/%s/queues/%s", projectID, locationID, queueID)

	// Build the Task payload.
	// https://godoc.org/google.golang.org/genproto/googleapis/cloud/tasks/v2#CreateTaskRequest
	req := &taskspb.CreateTaskRequest{
		Parent: queuePath,
		Task: &taskspb.Task{
			// https://godoc.org/google.golang.org/genproto/googleapis/cloud/tasks/v2#HttpRequest
			MessageType: &taskspb.Task_HttpRequest{
				HttpRequest: &taskspb.HttpRequest{
					HttpMethod: taskspb.HttpMethod_POST,
					Url:        url,
					AuthorizationHeader: &taskspb.HttpRequest_OidcToken{
						OidcToken: &taskspb.OidcToken{
							ServiceAccountEmail: email,
						},
					},
				},
			},
		},
	}

	// Add a payload message if one is present.
	req.Task.GetHttpRequest().Body = []byte(message)

	createdTask, err := client.CreateTask(ctx, req)
	if err != nil {
		return nil, fmt.Errorf("cloudtasks.CreateTask: %w", err)
	}

	return createdTask, nil
}

Node.js

// Imports the Google Cloud Tasks library.
const {CloudTasksClient} = require('@google-cloud/tasks');

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

async function createHttpTaskWithToken() {
  // TODO(developer): Uncomment these lines and replace with your values.
  // const project = 'my-project-id';
  // const queue = 'my-queue';
  // const location = 'us-central1';
  // const url = 'https://example.com/taskhandler';
  // const serviceAccountEmail = 'client@<project-id>.iam.gserviceaccount.com';
  // const payload = 'Hello, World!';

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

  const task = {
    httpRequest: {
      headers: {
        'Content-Type': 'text/plain', // Set content type to ensure compatibility your application's request parsing
      },
      httpMethod: 'POST',
      url,
      oidcToken: {
        serviceAccountEmail,
      },
    },
  };

  if (payload) {
    task.httpRequest.body = Buffer.from(payload).toString('base64');
  }

  console.log('Sending task:');
  console.log(task);
  // Send create task request.
  const request = {parent: parent, task: task};
  const [response] = await client.createTask(request);
  const name = response.name;
  console.log(`Created task ${name}`);
}
createHttpTaskWithToken();

请注意 package.json 文件:

{
  "name": "appengine-cloudtasks",
  "description": "Google App Engine Cloud Tasks example.",
  "license": "Apache-2.0",
  "author": "Google Inc.",
  "private": true,
  "engines": {
    "node": ">=16.0.0"
  },
  "files": [
    "*.js"
  ],
  "scripts": {
    "test": "c8 mocha -p -j 2 --timeout 30000",
    "start": "node server.js"
  },
  "dependencies": {
    "@google-cloud/tasks": "^4.0.0",
    "express": "^4.16.3"
  },
  "devDependencies": {
    "c8": "^8.0.0",
    "chai": "^4.2.0",
    "mocha": "^10.0.0",
    "uuid": "^9.0.0"
  }
}

提供您自己的 HTTP 目标任务处理程序

HTTP Target 任务处理程序与 App Engine 任务处理程序非常相似,但以下几项除外:

  • 超时:对于所有 HTTP 目标任务处理程序,默认超时时间为 10 分钟,最长为 30 分钟。
  • 身份验证逻辑:如果您要在目标服务中编写自己的代码来验证令牌,则应使用 ID 令牌。如需详细了解此方面信息,请参阅 OpenID Connect,尤其是验证 ID 令牌
  • 标头:HTTP 目标请求具有由队列设置的标头,其中包含处理程序可以使用的特定于任务的信息。这些标头与在App Engine 任务请求中设置的标头类似但不同。 这些标题仅提供相关信息。 它们应该用作身份来源。

    如果应用的外部用户请求中包含这些标头,则请将其替换为内部标头。唯一的例外情况是来自应用的已登录管理员的请求,管理员可以出于测试目的而设置标头。

    HTTP 目标请求始终包含以下标头:

    标头 说明
    X-CloudTasks-QueueName 队列名称。
    X-CloudTasks-TaskName 任务的“短”名称,或者系统为任务生成的唯一 ID(如果在创建时未指定任务名称)。这是整个任务名称中的 my-task-id 值,即 task_name = projects/my-project-id/locations/my-location/queues/my-queue-id/tasks/my-task-id
    X-CloudTasks-TaskRetryCount 此任务已经重试的次数。对于第一次尝试,该值为 0。此数字包括由于 5XX 错误代码导致任务失败而从未到达执行阶段的尝试次数。
    X-CloudTasks-TaskExecutionCount 任务从处理程序收到响应的总次数。由于 Cloud Tasks 在收到成功响应后会删除任务,因此所有先前的处理程序响应都是失败的。此数字不包括由于 5XX 错误代码而导致的失败。
    X-CloudTasks-TaskETA 任务的计划运行时间,以 1970 年 1 月 1 日以来的秒数指定。

    此外,来自 Cloud Tasks 的请求可能包含以下标头:

    标头 说明
    X-CloudTasks-TaskPreviousResponse 来自上一次重试的 HTTP 响应代码。
    X-CloudTasks-TaskRetryReason 重试任务的原因。

手动将 Cloud Tasks Service Agent 角色添加到 Cloud Tasks 服务账号

当您在 2019 年 3 月 19 日之前启用 Cloud Tasks API 的情况下,才需要执行此操作。

使用控制台

  1. Google Cloud 项目设置页面上找到您的项目编号。
  2. 复制该编号。
  3. 打开 IAM 管理控制台页面
  4. 点击授予访问权限。系统会打开授予访问权限屏幕。
  5. 添加主账号部分中,添加以下格式的电子邮件地址:

     service-PROJECT_NUMBER@gcp-sa-cloudtasks.iam.gserviceaccount.com
     

    PROJECT_NUMBER 替换为上面的项目编号。

  6. 分配角色部分中,搜索并选择 Cloud Tasks Service Agent

  7. 点击保存

使用 gcloud

  1. 查找您的项目编号:

        gcloud projects describe PROJECT_ID --format='table(projectNumber)'
        

    PROJECT_ID 替换为您的项目 ID。

  2. 复制该编号。

  3. 使用您复制的项目编号向 Cloud Tasks 服务账号授予 Cloud Tasks Service Agent 角色:

        gcloud projects add-iam-policy-binding PROJECT_ID --member serviceAccount:service-PROJECT_NUMBER@gcp-sa-cloudtasks.iam.gserviceaccount.com --role roles/cloudtasks.serviceAgent
    

    PROJECT_ID 替换为您的项目 ID,将 PROJECT_NUMBER 替换为上面的项目编号。

高级配置

您可以在任务中配置许多属性。如需查看完整列表,请参阅任务资源定义

您可以自定义的属性示例包括:

  • 命名:如果您选择为任务指定名称,Cloud Tasks 可以使用该名称来确保执行重复任务,但为此需要进行的处理会增加延迟时间。
  • 安排:您可以将任务安排在未来某个时间执行。仅支持 CreateTask(不支持 BufferTask
  • 重试配置:配置任务失败时的重试行为。仅支持 CreateTask(不支持 BufferTask

后续步骤