HTTP Target タスクの作成

このリリースの HTTP Targets では、Cloud Tasks ハンドラを、パブリック IP アドレスを持つ任意の HTTP エンドポイントで実行できるようになりました。このようなエンドポイントには、Cloud FunctionsCloud RunGKECompute Engine や、場合によってはオンプレミスのウェブサーバーなどがあります。こうしたサービスで、信頼性が高く構成が可能な方法でタスクを実行できるようになります。

このページでは、HTTP Target タスクをプログラムによって作成し、Cloud Tasks キューに入れる方法を説明します。 タスクを処理する場合は、新しいタスク オブジェクトを作成してキューに配置する必要があります。タスクを処理するサービスとハンドラを指定し、必要に応じてタスク固有のデータをハンドラに渡すこともできます。また、タスクを実行するタイミングをスケジューリングしたり、失敗した場合にタスクを再試行する回数を制限したりするなど、タスクの構成を微調整することもできます。タスクの名前を指定した場合、Cloud Tasks はその名前を使用してタスクの重複排除を行いますが、必要な処理によってレイテンシが増加する場合があります。

一般に、タスクは HTTP リクエストの形式で作成します。次の例のように、Google Cloud クライアント ライブラリサービス アカウントを使用することで、Cloud Tasks サーバーとの通信の詳細を管理でき、タスクの作成が簡単になります。

HTTP Target タスクの作成

次の例では、HTTP Target タスクのリクエストを作成します。このリクエストによって、タスクハンドラの URL をはじめとしてタスクが構成されます。

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

# 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'

# 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': 'POST',
            'url': url  # The full url path that the task will be sent to.
        }
}
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(parent, task)

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

requirements.txt ファイルをメモします。

google-cloud-tasks==1.5.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"?>
<!--
Copyright 2018 Google LLC

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
-->
<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>
  <version>1.0-SNAPSHOT</version>
  <groupId>com.example.task</groupId>
  <artifactId>tasks-samples</artifactId>

  <!--
    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.18</version>
  </parent>

  <properties>
    <maven.compiler.target>1.8</maven.compiler.target>
    <maven.compiler.source>1.8</maven.compiler.source>
    <failOnMissingWebXml>false</failOnMissingWebXml>
  </properties>

  <dependencies>
    <!-- Compile/runtime dependencies -->
    <dependency>
      <groupId>com.google.cloud</groupId>
      <artifactId>google-cloud-tasks</artifactId>
      <version>1.30.0</version>
    </dependency>
    <dependency>
      <groupId>com.google.protobuf</groupId>
      <artifactId>protobuf-java</artifactId>
      <version>3.12.2</version>
    </dependency>

    <!-- Test dependencies -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13</version>
    </dependency>
    <dependency>
      <groupId>com.google.truth</groupId>
      <artifactId>truth</artifactId>
      <version>1.0.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>3.3.0</version>
        <configuration>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
        </configuration>
        <executions>
          <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
              <goal>single</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</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();

// 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}`);

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.0",
    "body-parser": "^1.18.3",
    "express": "^4.16.3",
    "yargs": "^15.0.0"
  },
  "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 起動元のロールが必要です。作成したサービス アカウントまたはプロジェクト内の他のサービス アカウントを使用できます。

  12. Cloud Tasks 自体には、Cloud Tasks Service Agent ロールが付与された独自のサービス アカウントが必要です。これは、Cloud Tasks サービス アカウントに関連付けられた認証情報に基づいてヘッダー トークンを生成し、ハンドラ ターゲットで認証できるようにするためです。このロールが付与された Cloud Tasks のサービス アカウントは、Cloud Task API を有効にすると自動的に作成されます。ただし、2019 年 3 月 19 日より前にこの API を有効にしていた場合は、このロールを手動で追加する必要があります。

認証トークンがある HTTP Target タスクの使用

Cloud Tasks と HTTP Target ハンドラの間で認証を行うために、Cloud Tasks はヘッダー トークンを作成します。このトークンは、メールアドレスで識別される Cloud Tasks Enqueuer サービス アカウントの認証情報に基づいて生成されます。リクエストは、トークンとともに HTTPS を介してキューからハンドラに送信されます。OIDC トークン、OAuth トークンのいずれかを使用できます。OIDC トークンは、署名付きの JSON ウェブトークン(JWT)で、主に ID を表明するために使用されます。これはアクセス権を与える 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': '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(parent, task)

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

requirements.txt ファイルをメモします。

google-cloud-tasks==1.5.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"?>
<!--
Copyright 2018 Google LLC

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
-->
<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>
  <version>1.0-SNAPSHOT</version>
  <groupId>com.example.task</groupId>
  <artifactId>tasks-samples</artifactId>

  <!--
    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.18</version>
  </parent>

  <properties>
    <maven.compiler.target>1.8</maven.compiler.target>
    <maven.compiler.source>1.8</maven.compiler.source>
    <failOnMissingWebXml>false</failOnMissingWebXml>
  </properties>

  <dependencies>
    <!-- Compile/runtime dependencies -->
    <dependency>
      <groupId>com.google.cloud</groupId>
      <artifactId>google-cloud-tasks</artifactId>
      <version>1.30.0</version>
    </dependency>
    <dependency>
      <groupId>com.google.protobuf</groupId>
      <artifactId>protobuf-java</artifactId>
      <version>3.12.2</version>
    </dependency>

    <!-- Test dependencies -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13</version>
    </dependency>
    <dependency>
      <groupId>com.google.truth</groupId>
      <artifactId>truth</artifactId>
      <version>1.0.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>3.3.0</version>
        <configuration>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
        </configuration>
        <executions>
          <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
              <goal>single</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</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();

// 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}`);

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.0",
    "body-parser": "^1.18.3",
    "express": "^4.16.3",
    "yargs": "^15.0.0"
  },
  "devDependencies": {
    "chai": "^4.2.0",
    "mocha": "^8.0.0",
    "uuid": "^8.0.0"
  }
}

独自の HTTP Target タスクハンドラの指定

HTTP Target タスクハンドラは App Engine タスクハンドラとよく似ていますが、次の点が異なります。

  • タイムアウト: HTTP Target タスクハンドラでは、デフォルトのタイムアウトは 10 分、最大は 30 分です。
  • 認証ロジック: 対象とするサービスで独自のコードを作成してトークンを検証する場合は、OIDC トークンを使用する必要があります。この操作に関する詳細については、OpenID Connect の、特に ID トークンの検証をご覧ください。
  • ヘッダー: HTTP Target リクエストには、ハンドラが使用できるタスク固有の情報が含まれたキューによって、ヘッダーが設定されています。これらは App Engine タスク リクエストに設定されたヘッダーと似ていますが、同じではありません。これらのヘッダーは情報のみを提供します。これらは ID のソースとして使用しないでください

    アプリに対する外部ユーザー リクエストにこのようなヘッダーが含まれている場合、それらは内部ユーザー リクエストによって置換されます。ただし、ログイン済みのアプリケーション管理者からのリクエストは唯一の例外です。アプリケーション管理者は、テストの目的でこのヘッダーを設定することが許可されています。

    HTTP Target リクエストには、常に次のヘッダーが含まれます。

    ヘッダー 説明
    X-CloudTasks-QueueName キューの名前。
    X-CloudTasks-TaskName タスクの「省略」名。または、作成時に名前が指定されなかった場合は、システムによって生成された一意の ID です。これは、完全なタスク名(task_name = projects/my-project-id/locations/my-location/queues/my-queue-id/tasks/my-task-id)の my-task-id 値になります。
    X-CloudTasks-TaskRetryCount このタスクが再試行された回数。最初の試行の場合は、この値は 0 です。この試行回数には、インスタンス数不足が原因でタスクが異常終了したため実行フェーズに到達できなかった試行も含まれています。
    X-CloudTasks-TaskExecutionCount タスクがハンドラからレスポンスを受け取った合計回数。Cloud Tasks は成功のレスポンスを受け取った時点でタスクを削除するため、それ以前のハンドラからのレスポンスはすべて失敗を意味します。この回数には、インスタンス数不足が原因の失敗は含まれていません。
    X-CloudTasks-TaskETA タスクのスケジュール時間。1970 年 1 月 1 日からの秒数で指定されます。

    さらに、Cloud Tasks からのリクエストには次のヘッダーが含まれる場合もあります。

    ヘッダー 説明
    X-CloudTasks-TaskPreviousResponse 前回の再試行の HTTP レスポンス コード。
    X-CloudTasks-TaskRetryReason タスクを再試行する理由。

Cloud Tasks サービス アカウントに Cloud Tasks サービス エージェントの役割を追加

この操作は、Cloud Tasks API を 2019 年 3 月 19 日より前に有効にした場合のみ必要になります。

コンソールの使用

  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] は上記のプロジェクト番号に置き換えます。

次のステップ