创建 HTTP 目标任务

现在,Cloud Tasks 处理程序可以借助这一版本的 HTTP Targets 在任何具有公共 IP 地址的 HTTP 端点上运行,例如 Cloud FunctionsCloud RunGKECompute Engine,甚至是本地 Web 服务器。您可以通过可靠的、可配置的方式在上述任何服务中执行您的任务。

本页面介绍如何以编程方式创建 HTTP 目标任务并将其置于 Cloud Tasks 队列中。 如果您要处理任务,必须创建一个新的任务对象,并将其放到队列中。您可以指定用于处理任务的服务和处理程序,并且可以选择将特定于任务的数据传递给处理程序。您还可以微调任务的配置,例如,安排将来执行任务的时间,或者限制失败时希望重试任务的次数。如果您选择为任务指定名称,则 Cloud Tasks 可以使用该名称来确保任务重复信息删除,这可能会使必要的处理增加延迟时间。

一般来说,您需要以 HTTP 请求的形式创建任务。使用 Google Cloud 客户端库服务帐号(如以下示例所示)不仅可以帮助您管理与 Cloud Tasks 服务器的通信细节,而且可以让您更加轻松地创建任务。

创建 HTTP 目标任务

以下示例创建用于构建任务的 HTTP 目标任务请求,包括任务处理程序的网址。

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

"""Create a task for a given queue with an arbitrary payload."""

from google.cloud import tasks_v2
from google.protobuf import timestamp_pb2
import datetime
import json

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

# TODO(developer): Uncomment these lines and replace with your values.
# project = 'my-project-id'
# queue = 'my-queue'
# location = 'us-central1'
# url = 'https://example.com/task_handler'
# payload = 'hello' or {'param': 'value'} for application/json

# Construct the fully qualified queue name.
parent = client.queue_path(project, location, queue)

# Construct the request body.
task = {
    "http_request": {  # Specify the type of request.
        "http_method": tasks_v2.HttpMethod.POST,
        "url": url,  # The full url path that the task will be sent to.
    }
}
if payload is not None:
    if isinstance(payload, dict):
        # Convert dict to JSON string
        payload = json.dumps(payload)
        # specify http content-type to application/json
        task["http_request"]["headers"] = {"Content-type": "application/json"}

    # The API expects a payload of type bytes.
    converted_payload = payload.encode()

    # Add the payload to the request.
    task["http_request"]["body"] = converted_payload

if in_seconds is not None:
    # Convert "seconds from now" into an rfc3339 datetime string.
    d = datetime.datetime.utcnow() + datetime.timedelta(seconds=in_seconds)

    # Create Timestamp protobuf.
    timestamp = timestamp_pb2.Timestamp()
    timestamp.FromDatetime(d)

    # Add the timestamp to the tasks.
    task["schedule_time"] = timestamp

if task_name is not None:
    # Add the name to tasks.
    task["name"] = task_name

# Use the client to build and send the task.
response = client.create_task(request={"parent": parent, "task": task})

print("Created task {}".format(response.name))

请注意 requirements.txt 文件:

google-cloud-tasks==2.0.0

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.google.cloud</groupId>
  <artifactId>cloudtasks-snippets</artifactId>
  <packaging>jar</packaging>
  <name>Google Cloud Tasks Snippets</name>
  <url>https://github.com/googleapis/java-tasks</url>

  <!--
    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.0.21</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>16.1.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.1</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>com.google.truth</groupId>
      <artifactId>truth</artifactId>
      <version>1.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

PHP

use Google\Cloud\Tasks\V2\CloudTasksClient;
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 (isset($payload)) {
    $httpRequest->setBody($payload);
}

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

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

请注意 composer.json 文件:

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

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 "google.golang.org/genproto/googleapis/cloud/tasks/v2"
)

// 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: %v", err)
	}

	// 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: %v", 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!';

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

  const task = {
    httpRequest: {
      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: inSeconds + Date.now() / 1000,
    };
  }

  // Send create task request.
  console.log('Sending task:');
  console.log(task);
  const request = {parent, 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": ">=10"
  },
  "files": [
    "*.js"
  ],
  "scripts": {
    "test": "mocha",
    "start": "node server.js"
  },
  "dependencies": {
    "@google-cloud/tasks": "^2.1.2",
    "body-parser": "^1.18.3",
    "express": "^4.16.3"
  },
  "devDependencies": {
    "chai": "^4.2.0",
    "mocha": "^8.0.0",
    "uuid": "^8.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 Target 处理程序身份验证设置服务帐号

如果您拥有具有相应凭据的服务帐号来访问处理程序,那么Cloud Tasks 可以调用需要身份验证的 HTTP Target 处理程序。

如果您想使用当前的服务帐号,则。只需为其授予适当的角色即可。这些说明涵盖了专门为此函数新创建的服务帐号。

  1. 访问服务帐号控制台页面。

    转到“服务帐号”页面

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

  3. 点击 + 创建服务帐号。

  4. 为帐号指定一个显示名。控制台会为该帐号创建一个相关的电子邮件帐号名称。这是您引用该帐号的方式。如果需要,您还可以添加帐号说明。

  5. 点击创建。您将转到服务帐号权限界面。

  6. 点击选择角色下拉列表。

  7. 滚动到左侧列中的Cloud Tasks,然后选择右侧的Cloud Tasks Enqueuer。这将向服务帐号授予将任务添加到队列的权限。

  8. 点击 + 添加其他角色

  9. 点击新增的选择角色下拉列表。

  10. 滚动到左侧列中的服务帐号,然后选择右侧的服务帐号用户。此角色允许服务帐号授权队列使用服务帐号的凭据,并代表其创建令牌。

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

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

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

Cloud Tasks 会创建一个标头令牌用于在 Cloud Tasks 和 HTTP Target 处理程序之间进行身份验证。此令牌是基于 Cloud Tasks Enqueuer 服务帐号的凭据,其标识为该电子邮件地址系统通过队列将具有令牌的请求从 HTTPS 发送到处理程序。 您可以使用 OIDC 令牌也可以使用 OAuth 令牌。OIDC 令牌已签名 JSON 网络令牌 (JWT),主要用于声明身份但不提供针对资源的任何隐式授权,这与提供访问权限的 OAuth 令牌不同。OIDC 令牌通常用于在 Google Cloud 上运行的任何处理程序,例如在 Cloud Functions 或 Cloud Run 上运行。在 *.googleapis.com 上托管的 Google API 除外:这些 API 需要 OAuth 令牌。您可以在请求本身中指定 OIDC 令牌或 OAuth 令牌。

以下示例创建任务请求,其中还包括标头令牌的创建。示例中使用了 OIDC 令牌。要使用 OAuth 令牌,请在构造请求时将 OIDC 参数替换为相应语言的 OAuth 参数。

Python

"""Create a task for a given queue with an arbitrary payload."""

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

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

# TODO(developer): Uncomment these lines and replace with your values.
# project = 'my-project-id'
# queue = 'my-queue'
# location = 'us-central1'
# url = 'https://example.com/task_handler'
# service_account_email = 'service-account@my-project-id.iam.gserviceaccount.com';
# payload = 'hello'

# Construct the fully qualified queue name.
parent = client.queue_path(project, location, queue)

# Construct the request body.
task = {
    "http_request": {  # Specify the type of request.
        "http_method": tasks_v2.HttpMethod.POST,
        "url": url,  # The full url path that the task will be sent to.
        "oidc_token": {"service_account_email": service_account_email},
    }
}

if payload is not None:
    # The API expects a payload of type bytes.
    converted_payload = payload.encode()

    # Add the payload to the request.
    task["http_request"]["body"] = converted_payload

if in_seconds is not None:
    # Convert "seconds from now" into an rfc3339 datetime string.
    d = datetime.datetime.utcnow() + datetime.timedelta(seconds=in_seconds)

    # Create Timestamp protobuf.
    timestamp = timestamp_pb2.Timestamp()
    timestamp.FromDatetime(d)

    # Add the timestamp to the tasks.
    task["schedule_time"] = timestamp

if task_name is not None:
    # Add the name to tasks.
    task["name"] = task_name

# Use the client to build and send the task.
response = client.create_task(request={"parent": parent, "task": task})

print("Created task {}".format(response.name))
return response

请注意 requirements.txt 文件:

google-cloud-tasks==2.0.0

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.google.cloud</groupId>
  <artifactId>cloudtasks-snippets</artifactId>
  <packaging>jar</packaging>
  <name>Google Cloud Tasks Snippets</name>
  <url>https://github.com/googleapis/java-tasks</url>

  <!--
    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.0.21</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>16.1.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.1</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>com.google.truth</groupId>
      <artifactId>truth</artifactId>
      <version>1.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

Go

import (
	"context"
	"fmt"

	cloudtasks "cloud.google.com/go/cloudtasks/apiv2"
	taskspb "google.golang.org/genproto/googleapis/cloud/tasks/v2"
)

// 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: %v", err)
	}

	// 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: %v", 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: {
      httpMethod: 'POST',
      url,
      oidcToken: {
        serviceAccountEmail,
      },
    },
  };

  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: inSeconds + Date.now() / 1000,
    };
  }

  console.log('Sending task:');
  console.log(task);
  // Send create task request.
  const request = {parent, 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": ">=10"
  },
  "files": [
    "*.js"
  ],
  "scripts": {
    "test": "mocha",
    "start": "node server.js"
  },
  "dependencies": {
    "@google-cloud/tasks": "^2.1.2",
    "body-parser": "^1.18.3",
    "express": "^4.16.3"
  },
  "devDependencies": {
    "chai": "^4.2.0",
    "mocha": "^8.0.0",
    "uuid": "^8.0.0"
  }
}

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

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

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

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

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

    标头 说明
    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. 点击 Add。 系统会打开 Add members 界面。
  5. 在“新成员”对话框中,添加以下格式的电子邮件地址:

    service-[project-number]@gcp-sa-cloudtasks.iam.gserviceaccount.com
    

    [project-number] 替换为上面的项目编号。

  6. Select a role 下拉列表中选择 Service Management -> Cloud Tasks Service Agent

  7. 点击 Save

使用 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] 替换为上面的项目编号。

后续步骤