HTTP 대상 태스크 만들기

Cloud Tasks 핸들러는 GKE, Compute Engine, 온프레미스 웹 서버와 같이 외부 IP 주소가 있는 모든 HTTP 엔드포인트에서 실행할 수 있습니다. 안정적이고 구성 가능한 방식으로 이러한 서비스에서 태스크를 실행할 수 있습니다.

이 페이지에서는 프로그래매틱 방식으로 기본 HTTP 대상 태스크를 만들어 Cloud Tasks 큐에 배치하는 방법을 보여줍니다.

(일반적이지 않은 명시적인 App Engine 대상과 달리) HTTP 대상이 있는 태스크의 경우 태스크를 만드는 방법이 두 가지 있습니다.

  • BufferTask 메서드: 큐가 서비스 앞에 태스크를 버퍼링하도록 설정된 경우 이 메서드를 사용합니다. 큐에 큐 수준 라우팅이 있어야 합니다. 대부분의 사용 사례에 가장 적합한 접근 방식입니다. 이 접근 방식은 BufferTask 메서드를 사용합니다.

  • CreateTask 메서드: 더 복잡합니다. 태스크 객체를 명시적으로 만들어야 합니다. 큐의 태스크에 다른 라우팅 구성이 있는 경우 이 메서드를 사용합니다. 이 경우 태스크 수준에서 라우팅을 지정하고 큐 수준 라우팅을 사용할 수 없습니다. 이 접근 방식은 CreateTask 메서드를 사용합니다.

기본 태스크 생성(BufferTask 메서드)

이 섹션에서는 HTTP 요청을 전송하여 태스크를 만드는 방법을 설명합니다. 사용하는 메서드는 BufferTask입니다.

제한사항

BufferTask 메서드에는 다음과 같은 제한사항이 적용됩니다.

  • 클라이언트 라이브러리: BufferTask 메서드는 클라이언트 라이브러리에서 지원되지 않습니다.

  • RPC API: RPC API에서는 BufferTask 메서드가 지원되지 않습니다.

  • 태스크 수준 라우팅: 이 메서드는 태스크 수준 라우팅을 지원하지 않습니다. 이 방법으로 태스크를 만들면 라우팅 정보를 추가하는 단계가 없으므로 큐 수준 라우팅을 사용해야 합니다. 그렇지 않으면 태스크에 라우팅 정보가 없게 됩니다. 큐에서 아직 큐 수준 라우팅을 사용하지 않는 경우 HTTP 태스크에 큐 수준 라우팅 구성을 참조하세요.

BufferTask 메서드 호출

다음 예에서는 Cloud Tasks API buffer 엔드포인트에 HTTP POST 요청을 전송하여 태스크를 만드는 방법을 보여줍니다.

curl

다음 코드 스니펫은 curl을 사용하는 BufferTask 메서드를 사용하여 태스크를 만드는 예시를 보여줍니다.

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

다음을 바꿉니다.

  • HTTP_METHOD: 요청의 HTTP 메서드(예: GET 또는 POST)
  • PROJECT_ID: Google Cloud 프로젝트의 ID입니다. 터미널에서 다음을 실행하여 가져올 수 있습니다.
    gcloud config get-value project
  • LOCATION: 큐의 위치
  • QUEUE_ID: 큐의 ID

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 send task to.
        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 doesn't 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

고급 태스크 생성(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;
    }
}

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
}

자바

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>

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": "^5.0.0",
    "express": "^4.16.3"
  },
  "devDependencies": {
    "c8": "^10.0.0",
    "chai": "^4.5.0",
    "mocha": "^10.0.0",
    "uuid": "^10.0.0"
  }
}

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"
    }
}

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

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 대상 핸들러 인증을 위한 서비스 계정 설정

Cloud Tasks는 핸들러에 액세스할 적절한 사용자 인증 정보가 있는 서비스 계정을 가진 경우 인증이 필요한 HTTP 대상 핸들러를 호출할 수 있습니다.

사용하려는 현재 서비스 계정이 있는 경우 가능합니다. 적절한 역할을 부여하기만 하면 됩니다. 이 안내에서는 이 기능에 필요한 새 서비스 계정 생성에 대해 다룹니다. Cloud Tasks 인증에 사용되는 기존 또는 새 서비스 계정은 Cloud Tasks 큐와 동일한 프로젝트에 있어야 합니다.

  1. Google Cloud 콘솔에서 서비스 계정 페이지로 이동합니다.

    서비스 계정으로 이동

  2. 필요한 경우 적절한 프로젝트를 선택합니다.

  3. 서비스 계정 만들기를 클릭합니다.

  4. 서비스 계정 세부정보 섹션에서 계정의 이름을 지정합니다. 콘솔이 계정의 관련 이메일 계정 이름을 생성합니다. 이런 방식으로 계정을 참조합니다. 계정의 용도에 대한 설명을 추가할 수도 있습니다. 만들고 계속하기를 클릭합니다.

  5. 이 서비스 계정에 프로젝트에 대한 액세스 권한 부여 섹션에서 역할 선택을 클릭합니다. Cloud Tasks 큐 추가자를 검색하여 선택합니다. 이 역할은 태스크를 큐에 추가할 수 있는 권한을 서비스 계정에 부여합니다.

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

  7. 역할 선택을 클릭합니다. 서비스 계정 사용자를 검색하여 선택합니다. 이 역할을 사용하면 대신 서비스 계정의 사용자 인증 정보를 사용하여 토큰을 만들도록 서비스 계정에서 큐를 승인할 수 있습니다.

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

  9. 완료를 클릭하여 서비스 계정 만들기를 마칩니다.

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

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

Cloud Tasks와 인증이 필요한 HTTP 대상 핸들러 간 인증을 위해 Cloud Tasks는 헤더 토큰을 만듭니다. 이 토큰은 이메일 주소로 식별되는 Cloud Tasks Enqueuer 서비스 계정의 사용자 인증 정보를 기반으로 합니다. 인증에 사용되는 서비스 계정은 Cloud Tasks 큐가 있는 동일한 프로젝트에 속해야 합니다. 헤더 토큰과 함께 요청이 HTTPS를 통해 큐에서 핸들러로 전송됩니다. ID 토큰이나 액세스 토큰을 사용할 수 있습니다. ID 토큰은 일반적으로 Google Cloud(예: Cloud Run Functions 또는 Cloud Run)에서 실행되는 모든 핸들러에 사용되어야 합니다. 액세스 토큰이 필요한 API와 같은 *.googleapis.com에서 호스팅되는 Google API는 예외입니다.

큐 수준 또는 태스크 수준에서 인증을 구성할 수 있습니다. 큐 수준에서 인증을 구성하려면 Cloud Tasks 큐 만들기를 참조하세요. 인증이 큐 수준에서 구성된 경우 이 구성은 태스크 수준의 구성을 재정의합니다. 태스크 수준에서 인증을 구성하려면 태스크 자체에서 ID(OIDC) 토큰 또는 액세스(OAuth) 토큰을 지정합니다.

BufferTask 메서드

다음 예에서는 태스크를 만들기 위해 BufferTask 메서드를 사용할 때 애플리케이션 기본 사용자 인증 정보를 사용하여 인증합니다.

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 메서드(예: GET 또는 POST)
  • 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

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 send task to.
        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 doesn't 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

CreateTask 메서드

다음 예에서는 Cloud Tasks 클라이언트 라이브러리와 함께 CreateTask 메서드를 사용하여 헤더 토큰 생성도 포함된 태스크를 만듭니다. 예시에서는 ID 토큰을 사용합니다. 액세스 토큰을 사용하려면 요청을 작성할 때 OIDC 매개변수를 언어에 적합한 OAuth 매개변수로 바꿉니다.

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
}

자바

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>

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": "^5.0.0",
    "express": "^4.16.3"
  },
  "devDependencies": {
    "c8": "^10.0.0",
    "chai": "^4.5.0",
    "mocha": "^10.0.0",
    "uuid": "^10.0.0"
  }
}

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

자체 HTTP 대상 태스크 핸들러 제공

HTTP Target 태스크 핸들러는 App Engine 태스크 핸들러와 매우 비슷하지만 다음과 같은 차이점이 있습니다.

  • 제한 시간: 모든 HTTP 대상 태스크 핸들러의 기본 제한 시간은 10분이며 최대 시간은 30분입니다.
  • 인증 로직: 타겟 서비스에서 토큰을 검증하는 코드를 직접 작성하는 경우 ID 토큰을 사용해야 합니다. 이와 관련된 자세한 내용은 OpenID Connect, 특히 ID 토큰 검증을 참조하세요.
  • 헤더: HTTP 대상 요청에 핸들러가 사용할 수 있는 작업별 정보가 포함된 큐에 의해 설정된 헤더가 있습니다. 이는 App Engine 작업 요청에 설정된 헤더와 유사하지만 동일하지는 않습니다. 이 헤더는 정보만 제공합니다. ID 소스로 사용하면 안 됩니다.

    앱에 대한 외부 사용자 요청에 이러한 헤더가 있는 경우 내부 헤더로 대체됩니다. 테스트용 헤더를 설정할 수 있는 로그인한 애플리케이션 관리자가 보내는 요청만이 유일한 예외입니다.

    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 서비스 계정에 Cloud Tasks 서비스 에이전트 역할을 수동으로 추가

이 작업은 Cloud Tasks API를 2019년 3월 19일 이전에 사용 설정한 경우에만 필요합니다.

콘솔

  1. Google Cloud 프로젝트 설정 페이지에서 프로젝트의 프로젝트 번호를 찾습니다.
  2. 번호를 복사해 둡니다.
  3. IAM 관리 콘솔 페이지를 엽니다.
  4. 액세스 권한 부여를 클릭합니다. 액세스 권한 부여 화면이 열립니다.
  5. 주 구성원 추가 섹션에서 다음과 같은 형식의 이메일 주소를 추가합니다.

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

    PROJECT_NUMBER를 Google Cloud 프로젝트 번호로 바꿉니다.

  6. 역할 할당 섹션에서 Cloud Tasks 서비스 에이전트를 검색하여 선택합니다.

  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: Google Cloud 프로젝트 ID
    • PROJECT_NUMBER: Google Cloud 프로젝트 번호입니다.

고급 구성

태스크에 여러 속성을 구성할 수 있습니다. 전체 목록은 태스크 리소스 정의를 참조하세요.

맞춤설정할 수 있는 속성의 예는 다음과 같습니다.

  • 이름 지정: 태스크의 이름을 지정하면 Cloud Tasks에서 이 이름을 사용하여 태스크 중복 삭제를 진행할 수 있지만, 이에 필요한 처리로 지연 시간이 늘어날 수 있습니다.
  • 예약: 태스크를 미래 시간으로 예약할 수 있습니다. CreateTask에서만 지원됩니다(BufferTask에서는 지원되지 않음).
  • 재시도 구성: 태스크가 실패할 경우 태스크의 재시도 동작을 구성합니다. CreateTask에서만 지원됩니다(BufferTask에서는 지원되지 않음).

다음 단계