Mengeksekusi tugas asinkron

Anda dapat menggunakan Cloud Tasks untuk mengantrekan tugas dengan aman agar diproses secara asinkron oleh layanan Cloud Run. Kasus penggunaan yang umum mencakup:

  • Mempertahankan permintaan melalui insiden produksi yang tidak terduga
  • Memperlancar lonjakan traffic dengan menunda pekerjaan yang tidak ditampilkan kepada pengguna
  • Mempercepat waktu respons pengguna dengan mendelegasikan operasi latar belakang yang lambat untuk ditangani oleh layanan yang lain, seperti update database atau batch processing
  • Membatasi tarif panggilan untuk layanan pendukung seperti database dan API pihak ketiga

Halaman ini menunjukkan cara mengantrekan tugas yang dikirim dengan aman melalui protokol HTTPS menuju layanan Cloud Run pribadi. Panduan ini menjelaskan perilaku yang diperlukan untuk layanan Cloud Run pribadi, izin akun layanan yang diperlukan, pembuatan task queue, dan pembuatan tugas.

Sebelum memulai

Aktifkan Cloud Tasks API pada project yang Anda gunakan.

Men-deploy layanan Cloud Run untuk menangani tugas

Untuk men-deploy layanan yang menerima tugas yang dikirim ke task queue, deploy layanan dengan cara yang sama seperti layanan Cloud Run lainnya. Layanan Cloud Run harus menampilkan kode 200 HTTP untuk mengonfirmasi keberhasilan setelah pemrosesan tugas selesai.

Tugas akan dikirim ke layanan Cloud Run ini sebagai permintaan HTTPS oleh Cloud Tasks.

Respons terhadap Cloud Tasks harus muncul dalam waktu tungguyang dikonfigurasi. Untuk beban kerja yang perlu berjalan lebih lama dari waktu tunggu Cloud Tasks maksimum, pertimbangkan untuk menggunakan pekerjaan Cloud Run.

Deploy dengan Terraform

Untuk mempelajari cara menerapkan atau menghapus konfigurasi Terraform, lihat Perintah dasar Terraform.

Untuk membuat layanan, tambahkan kode berikut ke file .tf Anda:

resource "google_cloud_run_v2_service" "default" {
  name     = "cloud-run-task-service"
  location = "us-central1"

  template {
    containers {
      image = "us-docker.pkg.dev/cloudrun/container/hello"
    }
  }
}

Membuat antrean tugas

Command line

Untuk membuat task queue, gunakan perintah

gcloud tasks queues create QUEUE-ID

mengganti QUEUE-ID dengan nama yang ingin Anda berikan ke task queue Anda: nama harus bersifat unik dalam project Anda. Jika Anda diminta untuk membuat aplikasi App Engine di project Anda, respons menggunakan y untuk membuatnya. Cloud Tasks menggunakannya untuk antrean: pastikan Anda memilih lokasi yang sama dengan yang Anda gunakan untuk layanan Cloud Run Anda.

Pada umumnya, konfigurasi task queue default akan berfungsi. Namun, Anda dapat secara opsional menetapkan batas kapasitas dan parameter percobaan ulang yang berbeda jika menginginkannya.

Terraform

Untuk mempelajari cara menerapkan atau menghapus konfigurasi Terraform, lihat Perintah dasar Terraform.

Untuk membuat task queue, tambahkan kode berikut ke file .tf Anda:

resource "google_cloud_tasks_queue" "default" {
  name     = "cloud-tasks-queue-name"
  location = "us-central1"
}

Terapkan perubahan dengan memasukkan terraform apply.

Membuat akun layanan untuk dikaitkan dengan tugas

Anda harus membuat akun layanan yang akan dikaitkan dengan tugas yang diantrekan. Akun layanan ini harus memiliki peran IAM Cloud Run Invoker untuk mengizinkan task queue mengirim tugas ke layanan Cloud Run. .

Konsol

  1. Di Konsol Google Cloud, buka halaman Akun layanan.

    Buka Akun Layanan

  2. Pilih project.

  3. Masukkan nama akun layanan untuk ditampilkan di Google Cloud Console.

    Konsol Google Cloud membuat ID akun layanan berdasarkan nama ini. Edit ID jika diperlukan. Anda tidak dapat mengubah ID nanti.

  4. (Opsional) Masukkan deskripsi tentang akun layanan.

  5. Klik Buat dan lanjutkan.

  6. Opsional: Klik kolom Pilih peran.

  7. Pilih Cloud Run > Cloud Run Invoker.

  8. Klik Done.

Command line

  1. Buat akun layanan:

    gcloud iam service-accounts create SERVICE_ACCOUNT_NAME \
       --display-name "DISPLAYED_SERVICE_ACCOUNT_NAME"

    Ganti

    • SERVICE_ACCOUNT_NAME dengan nama huruf kecil unik dalam project Google Cloud Anda, misalnya my-invoker-service-account-name.
    • DISPLAYED_SERVICE_ACCOUNT_NAME dengan nama yang ingin Anda tampilkan untuk akun layanan ini, misalnya, di konsol, misalnya, My Invoker Service Account.
  2. Untuk Cloud Run, beri akun layanan Anda izin untuk memanggil layanan Anda:

    gcloud run services add-iam-policy-binding SERVICE \
       --member=serviceAccount:SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com \
       --role=roles/run.invoker

    Ganti

    • SERVICE dengan nama layanan yang ingin Anda panggil oleh Cloud Tasks.
    • SERVICE_ACCOUNT_NAME dengan nama akun layanan.
    • PROJECT_ID dengan ID project Google Cloud Anda.
  3. Beri akun layanan Anda akses ke project sehingga ia memiliki izin untuk menyelesaikan tindakan tertentu pada resource di project Anda:

    gcloud projects add-iam-policy-binding RESOURCE_ID \
       --member=PRINCIPAL --role=roles/run.invoker

    Ganti

    • RESOURCE_ID: ID project Google Cloud Anda.

    • PRINCIPAL: ID untuk akun utama, atau anggota, yang biasanya memiliki formulir berikut: PRINCIPAL_TYPE:ID. Misalnya, user:my-user@example.com. Untuk daftar lengkap nilai yang dapat dimiliki PRINCIPAL, lihat referensi Binding Kebijakan.

Terraform

Untuk mempelajari cara menerapkan atau menghapus konfigurasi Terraform, lihat Perintah dasar Terraform.

Tambahkan berikut ini ke file .tf:

Buat akun layanan:

resource "google_service_account" "default" {
  account_id   = "cloud-run-task-invoker"
  display_name = "Cloud Run Task Invoker"
}

Untuk Cloud Run, beri akun layanan Anda izin untuk memanggil layanan Anda:

resource "google_cloud_run_service_iam_binding" "default" {
  location = google_cloud_run_v2_service.default.location
  service  = google_cloud_run_v2_service.default.name
  role     = "roles/run.invoker"
  members  = ["serviceAccount:${google_service_account.default.email}"]
}

Terapkan perubahan dengan memasukkan terraform apply.

Membuat tugas HTTP dengan token autentikasi

Saat Anda membuat tugas untuk dikirim ke task queue, Anda menentukan project, lokasi, nama antrean, email akun layanan yang dibuat sebelumnya yang akan dikaitkan dengan tugas, URL layanan Cloud Run pribadi yang akan menjalankan tugas, dan data lain yang perlu Anda kirim. Anda dapat memilih untuk melakukan hardcode pada nilai-nilai ini, meskipun nilai seperti project ID, lokasi, dan email akun layanan dapat diambil secara dinamis dari server metadata Cloud Run.

Baca dokumentasi Cloud Tasks API untuk mengetahui detail tentang isi permintaan tugas. Perhatikan bahwa permintaan yang berisi payload data harus menggunakan metode PUT atau POST HTTP.

Kode yang mengantrekan tugas harus memiliki izin IAM yang diperlukan untuk melakukannya, seperti peran Penyisip Cloud Tasks. Kode Anda akan memiliki izin IAM yang diperlukan jika Anda menggunakan akun layanan default di Cloud Run.

Contoh berikut membuat permintaan tugas yang juga menyertakan pembuatan token header. Token OIDC digunakan dalam contoh. Untuk menggunakan token OAuth, ganti parameter OIDC dengan parameter OAuth yang sesuai bahasa dalam membuat permintaan.

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,
        )
    )

Perhatikan file requirements.txt:

google-cloud-tasks==2.13.1

Java

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

public class CreateHttpTaskWithToken {

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

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

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

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

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

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

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

Perhatikan file pom.xml:

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

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

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

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

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

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

Go

import (
	"context"
	"fmt"

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

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

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

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

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

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

	return createdTask, nil
}

Node.js

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

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

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

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

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

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

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

Perhatikan file package.json:

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

Langkah selanjutnya