HTTP Target 태스크 만들기

HTTP Targets가 출시됨에 따라 이제 공개 IP 주소를 갖는 모든 HTTP 엔드포인트(예: Cloud Functions, Cloud Run, GKE, Compute Engine, 심지어 온프렘 웹 서버도)에서 Cloud Tasks 핸들러를 실행할 수 있습니다. 안정적이고 구성 가능한 방식으로 이러한 서비스에서 태스크를 실행할 수 있습니다.

이 페이지에서는 프로그래매틱 방식으로 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
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

자바

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.21</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.3</version>
    </dependency>
    <dependency>
      <groupId>com.google.protobuf</groupId>
      <artifactId>protobuf-java</artifactId>
      <version>3.13.0</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.1",
    "body-parser": "^1.18.3",
    "express": "^4.16.3",
    "yargs": "^16.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 큐 추가자를 선택합니다. 이렇게 하면 태스크를 큐에 추가 할 수 있는 권한이 서비스 계정에 부여됩니다.

  8. + 다른 역할 추가를 클릭합니다.

  9. 역할 선택 드롭다운을 클릭합니다.

  10. 왼쪽 열에서 서비스 계정으로 스크롤하고 오른쪽에서 서비스 계정 사용자를 선택합니다. 이 역할을 사용하면 서비스 계정의 사용자 인증 정보를 사용하여 대신 토큰을 만들도록 서비스 계정에서 큐를 승인할 수 있습니다.

  11. 핸들러가 Google Cloud의 일부인 경우 핸들러가 실행 중인 서비스에 액세스하는 것과 관련된 역할을 서비스 계정에 부여하세요. Google Cloud에 포함된 각 서비스에는 서로 다른 역할이 필요합니다. 예를 들어 Cloud Run에서 핸들러에 액세스하려면 Cloud Run 호출자 역할이 필요한 것 등입니다. 방금 만든 서비스 계정 또는 프로젝트의 다른 서비스 계정을 사용할 수 있습니다.

  12. Cloud Tasks 자체에는 Cloud Tasks Service Agent 역할이 부여된 자체 서비스 계정이 있어야 합니다. 이렇게 하면 Cloud Tasks 서비스 계정과 연결된 사용자 인증 정보를 기반으로 헤더 토큰을 생성하여 핸들러 대상으로 인증할 수 있습니다. Cloud Task API를 사용 설정하면 이 역할이 부여된 Cloud Tasks 서비스 계정이 자동으로 생성됩니다. , API를 2019년 3월 19일 이전에 사용 설정했다면 역할을 수동으로 추가해야 합니다.

인증 토큰이 포함된 HTTP Target 태스크 사용

Cloud Tasks와 HTTP Target 핸들러 간의 인증을 위해 Cloud Tasks는 헤더 토큰을 만듭니다. 이 토큰은 이메일 주소로 식별되는 Cloud Tasks Enqueuer 서비스 계정의 사용자 인증 정보를 기반으로 합니다. 토큰과 함께 요청이 HTTPS를 통해 큐에서 핸들러로 전송됩니다. 이때 OIDC 토큰 또는 OAuth 토큰을 사용할 수 있습니다. OIDC 토큰은 서명된 JSON 웹 토큰(JWT)이며 주로 ID를 어설션하고, 액세스를 제공하는 OAuth 토큰과는 달리 암시적 승인을 제공하지 않습니다. OIDC 토큰은 일반적으로 Cloud Functions 또는 Cloud Run과 같은 Google Cloud에서 실행되는 모든 핸들러에 사용해야 합니다. 예외는 OAuth 토큰을 필요로 하는 *.googleapis.com에서 호스팅되는 Google API입니다. 요청 자체에 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

자바

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.21</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.3</version>
    </dependency>
    <dependency>
      <groupId>com.google.protobuf</groupId>
      <artifactId>protobuf-java</artifactId>
      <version>3.13.0</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.1",
    "body-parser": "^1.18.3",
    "express": "^4.16.3",
    "yargs": "^16.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입니다. 이것은 완전한 태스크 이름의 my-task-id 값입니다. 즉, task_name = projects/my-project-id/locations/my-location/queues/my-queue-id/tasks/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]를 위의 프로젝트 번호로 바꿉니다.

다음 단계

  • RPC API 참조에서 HTTP 대상 태스크에 대해 자세히 알아보기
  • REST API 참조에서 HTTP Target 태스크에 대해 자세히 알아보기.