Pemicu dari Push Pub/Sub

Halaman ini menjelaskan tentang penggunaan Pub/Sub untuk push pesan ke endpoint layanan Cloud Run, tempat pesan selanjutnya dikirim ke container sebagai permintaan HTTP. Halaman ini menunjukkan cara mengaktifkan layanan Anda untuk memproses pesan yang dikirim dengan aman dari langganan Pub/Sub dalam project Google Cloud yang sama.

Dengan memanfaatkan akun layanan dan izin IAM, Anda dapat menggunakan Pub/Sub secara aman dan pribadi dengan Cloud Run, tanpa harus mengekspos layanan Cloud Run Anda ke publik. Hanya langganan Pub/Sub yang telah Anda siapkan yang dapat memanggil layanan.

Batas waktu konfirmasi untuk Cloud Run

Pastikan Anda menetapkan batas waktu konfirmasi langganan Pub/Sub (ackDeadlineSeconds) ke batas maksimum 600 detik. Layanan Cloud Run Anda harus mengonfirmasi pesan Pub/Sub dengan menampilkan respons dalam waktu 600 detik. Jika tidak, Pub/Sub akan mengirim ulang pesan, sehingga menyebabkan pemicu diduplikat layanan Cloud Run Anda.

Kasus penggunaan

Kemungkinan kasus penggunaan meliputi:

Ringkasan integrasi

Untuk mengintegrasikan layanan Anda dengan Pub/Sub,

  • Buat topik Pub/Sub.
  • Tambahkan kode di layanan Cloud Run untuk merespons pesan Pub/Sub yang dikirim ke topik yang Anda buat.
  • Buat akun layanan dengan izin yang diperlukan.
  • Buat langganan Pub/Sub lalu kaitkan dengan akun layanan. Langganan ini akan mengirim segala pesan ke layanan Anda berisikan pesan yang dipublikasikan ke topik tersebut.

Sebelum memulai

  • Siapkan lingkungan Anda seperti yang dijelaskan di halaman penyiapan untuk Cloud Run jika Anda belum melakukannya.
  • Dalam panduan ini, Anda diasumsikan sudah memiliki layanan Cloud Run dan ingin menambahkan kode yang dapat mengintegrasikannya dengan Pub/Sub. Jika Anda tidak memiliki layanan tersebut, alih-alih mengikuti halaman ini ada baiknya untuk menggunakan tutorial Cloud Run untuk Pub/Sub.

Menambahkan kode untuk menangani pesan dari Pub/Sub

Edit kode layanan yang ada untuk menambahkan kode yang diperlukan untuk mendukung Pub/Sub. Layanan Anda harus mengekstrak pesan dari permintaan dan menampilkan kode berhasil yang diharapkan. Cuplikan berikut menunjukkan cara melakukannya untuk membuat pesan Hello World sederhana dengan bahasa yang dipilih (Anda dapat menggunakan bahasa apa saja):

Node.js

app.post('/', (req, res) => {
  if (!req.body) {
    const msg = 'no Pub/Sub message received';
    console.error(`error: ${msg}`);
    res.status(400).send(`Bad Request: ${msg}`);
    return;
  }
  if (!req.body.message) {
    const msg = 'invalid Pub/Sub message format';
    console.error(`error: ${msg}`);
    res.status(400).send(`Bad Request: ${msg}`);
    return;
  }

  const pubSubMessage = req.body.message;
  const name = pubSubMessage.data
    ? Buffer.from(pubSubMessage.data, 'base64').toString().trim()
    : 'World';

  console.log(`Hello ${name}!`);
  res.status(204).send();
});

Python

@app.route("/", methods=["POST"])
def index():
    """Receive and parse Pub/Sub messages."""
    envelope = request.get_json()
    if not envelope:
        msg = "no Pub/Sub message received"
        print(f"error: {msg}")
        return f"Bad Request: {msg}", 400

    if not isinstance(envelope, dict) or "message" not in envelope:
        msg = "invalid Pub/Sub message format"
        print(f"error: {msg}")
        return f"Bad Request: {msg}", 400

    pubsub_message = envelope["message"]

    name = "World"
    if isinstance(pubsub_message, dict) and "data" in pubsub_message:
        name = base64.b64decode(pubsub_message["data"]).decode("utf-8").strip()

    print(f"Hello {name}!")

    return ("", 204)

Go


// PubSubMessage is the payload of a Pub/Sub event.
// See the documentation for more details:
// https://cloud.google.com/pubsub/docs/reference/rest/v1/PubsubMessage
type PubSubMessage struct {
	Message struct {
		Data []byte `json:"data,omitempty"`
		ID   string `json:"id"`
	} `json:"message"`
	Subscription string `json:"subscription"`
}

// HelloPubSub receives and processes a Pub/Sub push message.
func HelloPubSub(w http.ResponseWriter, r *http.Request) {
	var m PubSubMessage
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		log.Printf("ioutil.ReadAll: %v", err)
		http.Error(w, "Bad Request", http.StatusBadRequest)
		return
	}
	// byte slice unmarshalling handles base64 decoding.
	if err := json.Unmarshal(body, &m); err != nil {
		log.Printf("json.Unmarshal: %v", err)
		http.Error(w, "Bad Request", http.StatusBadRequest)
		return
	}

	name := string(m.Message.Data)
	if name == "" {
		name = "World"
	}
	log.Printf("Hello %s!", name)
}

Java

import com.example.cloudrun.Body;
import java.util.Base64;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

// PubsubController consumes a Pub/Sub message.
@RestController
public class PubSubController {
  @RequestMapping(value = "/", method = RequestMethod.POST)
  public ResponseEntity<String> receiveMessage(@RequestBody Body body) {
    // Get PubSub message from request body.
    Body.Message message = body.getMessage();
    if (message == null) {
      String msg = "Bad Request: invalid Pub/Sub message format";
      System.out.println(msg);
      return new ResponseEntity<>(msg, HttpStatus.BAD_REQUEST);
    }

    String data = message.getData();
    String target =
        !StringUtils.isEmpty(data) ? new String(Base64.getDecoder().decode(data)) : "World";
    String msg = "Hello " + target + "!";

    System.out.println(msg);
    return new ResponseEntity<>(msg, HttpStatus.OK);
  }
}

Anda harus membuat kode layanan untuk mengembalikan kode respons HTTP yang akurat. Kode berhasil, seperti HTTP 200 atau 204, mengonfirmasi pemrosesan lengkap pesan Pub/Sub. Kode error, seperti HTTP 400 atau 500, menunjukkan bahwa pesan akan dicoba lagi, seperti yang dijelaskan dalam Menerima pesan menggunakan Push.

Build lalu deploy layanan Cloud Run Anda setelah Anda mengupdatenya dengan kode Pub/Sub di atas.

Membuat akun layanan untuk langganan

Anda perlu membuat akun layanan untuk dikaitkan dengan langganan Pub/Sub dan memberinya izin untuk memanggil layanan Cloud Run. Pesan Pub/Sub yang dikirim ke layanan Cloud Run Anda akan membawa identitas akun layanan ini.

Anda dapat menggunakan akun layanan yang ada untuk merepresentasikan identitas langganan Pub/Sub, atau Anda dapat membuat yang baru.

Untuk membuat akun layanan baru dan memberinya izin memanggil 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 Konsol Google Cloud.

    Konsol Google Cloud membuat ID akun layanan berdasarkan nama ini. Edit ID jika perlu. Anda tidak dapat mengubah ID di kemudian hari.

  4. Opsional: Masukkan deskripsi akun layanan.

  5. Klik Create and continue.

  6. Opsional: Klik kolom Select a role.

  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 yang 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, di konsol, misalnya, My Invoker Service Account.
  2. Untuk Cloud Run, beri akun layanan Anda izin untuk memanggil layanan:

    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 dipanggil oleh Pub/Sub.
    • SERVICE_ACCOUNT_NAME dengan nama akun layanan.
    • PROJECT_ID dengan ID project Google Cloud Anda.
  3. Beri akun layanan ini akses ke project sehingga 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 bentuk 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.

  1. Untuk membuat akun layanan, tambahkan kode berikut ke file .tf yang sudah ada:

    resource "google_service_account" "sa" {
      account_id   = "cloud-run-pubsub-invoker"
      display_name = "Cloud Run Pub/Sub Invoker"
    }
  2. Untuk memberi akun layanan Anda izin agar dapat memanggil layanan, tambahkan kode berikut ke file .tf yang sudah ada:

    resource "google_cloud_run_service_iam_binding" "binding" {
      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.sa.email}"]
    }

Membuat topik Pub/Sub

Permintaan yang masuk ke layanan Anda muncul dipicu oleh pesan yang dipublikasikan ke topik Pub/Sub sehingga Anda harus membuat topik:

Konsol

  1. Buka halaman topik Pub/Sub di Konsol Google Cloud.

    Halaman topik Pub/Sub

  2. Klik Buat topik.

  3. Masukkan Nama unik untuk topik Anda, misalnya, MyTopic.

Command line

gcloud pubsub topics create TOPIC-NAME

Ganti TOPIC-NAME dengan nama topik yang unik dalam project Google Cloud Anda.

Terraform

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

Bagian ini menunjukkan cara menggunakan Terraform untuk menentukan layanan di konfigurasi Terraform, menggunakan resource google_pubsub_topic dari Penyedia Google Cloud Platform.

Tambahkan konten berikut ke file .tf yang sudah ada:

resource "google_pubsub_topic" "default" {
  name = "pubsub_topic"
}

Membuat langganan push dan mengaitkannya dengan akun layanan

Setelah membuat topik Pub/Sub, Anda harus berlangganan layanan untuk menerima pesan yang dikirim ke topik, dan Anda harus mengaitkan langganan dengan akun layanan yang Anda buat untuk layanan. Anda dapat menggunakan Konsol Google Cloud atau command line gcloud:

Konsol

  1. Buka halaman topik Pub/Sub.

    Halaman topik Pub/Sub

  2. Klik topik yang ingin dilanggan.

  3. Klik Buat Langganan untuk menampilkan formulir langganan:

    formulir langganan

    Di dalam formulir,

    1. Tentukan jenis pengiriman push.
    2. Untuk URL Endpoint, tentukan URL layanan Anda, yang ditampilkan di halaman detail layanan.
    3. Di menu dropdown Akun Layanan, pilih akun layanan yang Anda buat dengan izin yang diperlukan.
    4. Tetapkan akhir masa berlaku langganan dan batas waktu konfirmasi selama 600 detik.
    5. Klik Buat.
  4. Langganan selesai. Pesan yang diposting ke topik tersebut sekarang akan dikirim ke layanan Anda.

Command line

  1. Izinkan Pub/Sub membuat token autentikasi di project Anda:

    gcloud projects add-iam-policy-binding PROJECT-ID \
         --member=serviceAccount:service-PROJECT-NUMBER@gcp-sa-pubsub.iam.gserviceaccount.com \
         --role=roles/iam.serviceAccountTokenCreator

    Ganti

    • PROJECT-ID dengan ID project Google Cloud Anda.
    • PROJECT-NUMBER dengan nomor project Google Cloud Anda.

      Project ID dan nomor project tercantum di panel Project info di Konsol Google Cloud untuk project Anda.

  2. Buat langganan Pub/Sub dengan akun layanan yang Anda buat dengan izin yang diperlukan:

    gcloud pubsub subscriptions create SUBSCRIPTION-ID --topic TOPIC-NAME \
       --ack-deadline=600 \
       --push-endpoint=SERVICE-URL/ \
       --push-auth-service-account=SERVICE-ACCOUNT-NAME@PROJECT-ID.iam.gserviceaccount.com

    Ganti

    • TOPIC-NAME dengan topik yang dibuat sebelumnya.
    • SERVICE-URL dengan URL HTTP yang diberikan saat Anda men-deploy layanan. Anda dapat menemukannya dengan menggunakan perintah gcloud run services describe, dengan menentukan nama layanan Anda: cari baris nilai yang dimulai dengan domain.
    • PROJECT-ID dengan ID project Google Cloud Anda.

    Flag --push-auth-service-account mengaktifkan fungsi push Pub/Sub untuk Autentikasi dan otorisasi

    Perlu diperhatikan bahwa batas waktu konfirmasi ditetapkan ke maksimum 600 detik.

  3. Langganan selesai. Pesan yang diposting ke topik tersebut sekarang akan dikirim ke layanan Anda. Anda dapat mengirim pesan pengujian ke topik menggunakan perintah:

    gcloud pubsub topics publish TOPIC --message "hello"

    Ganti TOPIC dengan nama topik yang Anda buat.

Terraform

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

  1. Izinkan Pub/Sub membuat token autentikasi di project Anda. Tambahkan kode berikut ke file .tf Anda:

    resource "google_project_service_identity" "pubsub_agent" {
      provider = google-beta
      project  = data.google_project.project.project_id
      service  = "pubsub.googleapis.com"
    }
    
    resource "google_project_iam_binding" "project_token_creator" {
      project = data.google_project.project.project_id
      role    = "roles/iam.serviceAccountTokenCreator"
      members = ["serviceAccount:${google_project_service_identity.pubsub_agent.email}"]
    }
  2. Buat langganan Pub/Sub dengan akun layanan yang dibuat dengan izin yang diperlukan. Tambahkan kode berikut ke file .tf Anda:

    resource "google_pubsub_subscription" "subscription" {
      name  = "pubsub_subscription"
      topic = google_pubsub_topic.default.name
      push_config {
        push_endpoint = google_cloud_run_v2_service.default.uri
        oidc_token {
          service_account_email = google_service_account.sa.email
        }
        attributes = {
          x-goog-version = "v1"
        }
      }
      depends_on = [google_cloud_run_v2_service.default]
    }
  3. Langganan selesai. Pesan yang diposting ke topik tersebut kini akan dikirim ke layanan Anda. Anda dapat mengirim pesan pengujian ke topik menggunakan perintah:

    gcloud pubsub topics publish TOPIC --message "hello"

    Ganti TOPIC dengan nama topik yang Anda buat.

Langkah berikutnya