建立推送訂閱項目

本文說明如何建立發送訂閱項目。您可以使用Google Cloud 控制台、Google Cloud CLI、用戶端程式庫或 Pub/Sub API 建立推送訂閱項目。

事前準備

必要角色和權限

如要建立訂閱項目,您必須在專案層級設定存取權控管。如果訂閱項目和主題位於不同專案,您也需要資源層級的權限,本節稍後會說明這點。

如要取得建立推送訂閱項目所需的權限,請要求管理員授予您專案的 Pub/Sub 編輯者 (roles/pubsub.editor) 身分與存取權管理角色。如要進一步瞭解如何授予角色,請參閱「管理專案、資料夾和機構的存取權」。

這個預先定義的角色具備建立推送訂閱項目所需的權限。如要查看確切的必要權限,請展開「必要權限」部分:

所需權限

如要建立推送訂閱項目,必須具備下列權限:

  • 建立訂閱項目: pubsub.subscriptions.create
  • 刪除訂閱項目: pubsub.subscriptions.delete
  • 取得訂閱方案: pubsub.subscriptions.get
  • 列出訂閱項目: pubsub.subscriptions.list
  • 更新訂閱項目: pubsub.subscriptions.update
  • 將訂閱項目附加至主題: pubsub.topics.attachSubscription
  • 取得訂閱項目的 IAM 政策: pubsub.subscriptions.getIamPolicy
  • 為訂閱項目設定 IAM 政策 pubsub.subscriptions.setIamPolicy

您或許還可透過自訂角色或其他預先定義的角色取得這些權限。

如要在一個專案中建立與另一個專案主題相關聯的推送訂閱項目,請要求主題管理員也授予您該主題的 Pub/Sub 編輯者 (roles/pubsub.editor) IAM 角色。

推送訂閱屬性

設定推送訂閱項目時,您可以指定下列屬性。

常見屬性

瞭解可為所有訂閱項目設定的常見訂閱項目屬性

端點

端點網址 (必填)。可公開存取的 HTTPS 位址。推送端點的伺服器必須具備由憑證授權單位簽署的有效 SSL 憑證。Pub/Sub 服務會從 Pub/Sub 服務儲存訊息的 Google Cloud 區域,將訊息傳送至推送端點。Pub/Sub 服務會盡可能傳送來自相同 Google Cloud 區域的訊息。

  • 如果訂閱者使用防火牆,就無法接收推送要求。如要接收推送要求,請務必關閉防火牆,並驗證要求中使用的 JSON Web Token (JWT)。如果訂閱者有防火牆,您可能會收到 403 permission denied 錯誤訊息。

  • Pub/Sub 不再要求推送訂閱項目網址網域提供擁有權證明。如果網域收到來自 Pub/Sub 的非預期 POST 要求,可以回報疑似濫用行為

驗證

啟用驗證功能。啟用後,Pub/Sub 傳送至推送端點的訊息會包含授權標頭,讓端點驗證要求。與訂閱項目一起託管在相同專案中的 App Engine 標準應用程式和 Cloud Run 函式端點,都可以使用自動驗證和授權機制。

經過驗證的推送訂閱項目的驗證設定包含使用者管理的服務帳戶,以及在 createpatchModifyPushConfig 呼叫中指定的對象參數。您也必須將特定角色授予服務帳戶,詳情請參閱下一節。

  • 目標對象。Webhook 用來驗證這個特定符記目標對象的不區分大小寫字串。

  • 服務帳戶。Pub/Sub 會自動為您建立服務帳戶,格式為 service-{PROJECT_NUMBER}@gcp-sa-pubsub.iam.gserviceaccount.com

啟用驗證功能的事前準備

使用者管理的服務帳戶是與推送訂閱項目相關聯的服務帳戶。這個帳戶會做為產生的 JSON Web Token (JWT) 的 email 聲明。服務帳戶必須符合下列規定:

  • 這個使用者代管的服務帳戶必須與推送訂閱項目位於同一專案。

  • 建立或修改推送訂閱項目的主體必須對使用者管理的服務帳戶擁有 iam.serviceAccounts.actAs 權限,才能將服務帳戶附加至推送訂閱項目。詳情請參閱「將服務帳戶附加至資源」。

  • 必要權限:必須將 iam.serviceAccounts.getOpenIdToken 權限 (包含在 roles/iam.serviceAccountTokenCreator 角色中) 授予這個服務帳戶,Pub/Sub 才能為指定服務帳戶建立 JWT 權杖,以驗證推送要求。

酬載解除包裝

「啟用酬載解除包裝」選項會從 Pub/Sub 訊息中移除所有訊息中繼資料,只保留訊息資料。透過酬載解包,訊息資料會直接以 HTTP 主體的形式傳送。

您也可以啟用「寫入中繼資料」選項。「寫入中繼資料」選項會將先前移除的訊息中繼資料新增回要求標頭。

傳送至私人虛擬私有雲地址

Pub/Sub 在 VPC 網路外部運作,無法直接將訊息推送至私人 VPC 位址。不過,您可以使用 Eventarc 將訊息轉送至虛擬私有雲內的服務。Pub/Sub 可以將訊息推送至 Eventarc 觸發程序,然後將訊息轉送至虛擬私有雲中的服務,例如 Cloud Run 服務或 Workflows 執行作業。詳情請參閱 Eventarc 說明文件

VPC Service Controls

如果專案受到 VPC Service Controls 保護,請注意推送訂閱的下列限制:

  • 您只能為推送端點設為具有預設 run.app 網址的 Cloud Run 服務,或設為 Workflows 執行作業,建立新的推送訂閱項目。自訂網域無法運作。

  • 透過 Eventarc 將事件轉送至 Workflows 目的地時,如果推送端點設為 Workflows 執行作業,您只能透過 Eventarc 建立新的推送訂閱項目。

  • 您無法更新現有的推送訂閱項目,這些推送訂閱項目會繼續運作,但不會受到 VPC Service Controls 保護。

建立推送訂閱項目

下列範例示範如何使用提供的預設設定,建立採用推送傳送方式的訂閱項目。

根據預設,訂閱項目會使用提取傳送,除非您明確設定推送設定,如下列範例所示。

控制台

如要建立推送訂閱項目,請完成下列步驟:

  1. 前往 Google Cloud 控制台的「Subscriptions」(訂閱項目) 頁面。

    前往「訂閱項目」頁面

  2. 按一下「Create Subscription」 (建立訂閱項目)
  3. 在「Subscription ID」(訂閱項目 ID) 欄位中輸入名稱。

    如要瞭解如何命名訂閱項目,請參閱「主題或訂閱項目命名規範」。

  4. 從下拉式選單中選擇或建立主題。訂閱項目會接收來自主題的訊息。
  5. 將「傳送類型」選為「推送」
  6. 指定端點網址。
  7. 保留其他所有預設值。
  8. 點選「建立」

你也可以在「主題」部分建立訂閱項目。這個捷徑可將主題與訂閱項目建立關聯。

  1. 前往 Google Cloud 控制台的「主題」頁面。

    前往「主題」

  2. 按一下要建立訂閱項目的主題旁邊的
  3. 在內容選單中,選取「建立訂閱項目」
  4. 輸入「Subscription ID」(訂閱項目 ID)

    如要瞭解如何命名訂閱項目,請參閱「主題或訂閱項目命名規範」。

  5. 將「傳送類型」選為「推送」
  6. 指定端點網址。
  7. 保留其他所有預設值。
  8. 點選「建立」

gcloud

  1. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

    At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.

  2. 如要建立推送訂閱項目,請執行 gcloud pubsub subscriptions create 指令。

    gcloud pubsub subscriptions create SUBSCRIPTION_ID \
    --topic=TOPIC_ID \
    --push-endpoint=PUSH_ENDPOINT

    更改下列內容:

    • SUBSCRIPTION_ID:新推送訂閱項目的名稱或 ID。
    • TOPIC_ID:主題的名稱或 ID。
    • PUSH_ENDPOINT:做為這項訂閱項目端點的網址。 例如:https://myproject.appspot.com/myhandler
  3. REST

    如要建立推送訂閱項目,請使用 projects.subscriptions.create 方法:

    要求:

    要求必須透過 Authorization 標頭中的存取權杖進行驗證。如要取得目前應用程式預設憑證的存取權杖,請執行:gcloud auth application-default print-access-token

    PUT https://pubsub.googleapis.com/v1/projects/PROJECT_ID/subscriptions/SUBSCRIPTION_ID
    Authorization: Bearer ACCESS_TOKEN
    

    要求主體:

    {
    "topic": "projects/PROJECT_ID/topics/TOPIC_ID",
    // Only needed if you are using push delivery
    "pushConfig": {
    "pushEndpoint": "PUSH_ENDPOINT"
    }
    }

    其中:

  4. PROJECT_ID 是您的專案 ID。
  5. SUBSCRIPTION_ID 是您的訂閱 ID。
  6. TOPIC_ID 是主題 ID。
  7. PUSH_ENDPOINT 是做為端點的網址。例如:https://myproject.appspot.com/myhandler
  8. 回應:

    {
    "name": "projects/PROJECT_ID/subscriptions/SUBSCRIPTION_ID",
    "topic": "projects/PROJECT_ID/topics/TOPIC_ID",
    "pushConfig": {
    "pushEndpoint": "https://PROJECT_ID.appspot.com/myhandler",
    "attributes": {
      "x-goog-version": "v1"
    }
    },
    "ackDeadlineSeconds": 10,
    "messageRetentionDuration": "604800s",
    "expirationPolicy": {
    "ttl": "2678400s"
    }
    }

    C++

    在試用這個範例之前,請先按照快速入門:使用用戶端程式庫中的 C++ 設定操作說明進行操作。詳情請參閱 Pub/Sub C++ API 參考說明文件

    namespace pubsub = ::google::cloud::pubsub;
    namespace pubsub_admin = ::google::cloud::pubsub_admin;
    [](pubsub_admin::SubscriptionAdminClient client,
       std::string const& project_id, std::string const& topic_id,
       std::string const& subscription_id, std::string const& endpoint) {
      google::pubsub::v1::Subscription request;
      request.set_name(
          pubsub::Subscription(project_id, subscription_id).FullName());
      request.set_topic(pubsub::Topic(project_id, topic_id).FullName());
      request.mutable_push_config()->set_push_endpoint(endpoint);
      auto sub = client.CreateSubscription(request);
      if (sub.status().code() == google::cloud::StatusCode::kAlreadyExists) {
        std::cout << "The subscription already exists\n";
        return;
      }
      if (!sub) throw std::move(sub).status();
    
      std::cout << "The subscription was successfully created: "
                << sub->DebugString() << "\n";

    C#

    在嘗試這個範例之前,請先按照快速入門:使用用戶端程式庫中的 C# 設定操作說明進行操作。詳情請參閱 Pub/Sub C# API 參考說明文件

    
    using Google.Cloud.PubSub.V1;
    
    public class CreatePushSubscriptionSample
    {
        public Subscription CreatePushSubscription(string projectId, string topicId, string subscriptionId, string pushEndpoint)
        {
            SubscriberServiceApiClient subscriber = SubscriberServiceApiClient.Create();
            TopicName topicName = TopicName.FromProjectTopic(projectId, topicId);
            SubscriptionName subscriptionName = SubscriptionName.FromProjectSubscription(projectId, subscriptionId);
    
            PushConfig pushConfig = new PushConfig { PushEndpoint = pushEndpoint };
    
            // The approximate amount of time in seconds (on a best-effort basis) Pub/Sub waits for the
            // subscriber to acknowledge receipt before resending the message.
            var ackDeadlineSeconds = 60;
            var subscription = subscriber.CreateSubscription(subscriptionName, topicName, pushConfig, ackDeadlineSeconds);
            return subscription;
        }
    }

    Go

    以下範例使用 Go Pub/Sub 用戶端程式庫的主要版本 (v2)。如果您仍在使用第 1 版程式庫,請參閱第 2 版遷移指南。如要查看第 1 版程式碼範例清單,請參閱 已淘汰的程式碼範例

    在試用這個範例之前,請先按照快速入門:使用用戶端程式庫中的 Go 設定說明進行操作。詳情請參閱 Pub/Sub Go API 參考說明文件

    import (
    	"context"
    	"fmt"
    	"io"
    
    	"cloud.google.com/go/pubsub/v2"
    	"cloud.google.com/go/pubsub/v2/apiv1/pubsubpb"
    )
    
    func createWithEndpoint(w io.Writer, projectID, topic, subscription, endpoint string) error {
    	// projectID := "my-project-id"
    	// topic := "projects/my-project-id/topics/my-topic"
    	// subscription := "projects/my-project/subscriptions/my-sub"
    	// endpoint := "https://my-test-project.appspot.com/push"
    	ctx := context.Background()
    	client, err := pubsub.NewClient(ctx, projectID)
    	if err != nil {
    		return fmt.Errorf("pubsub.NewClient: %w", err)
    	}
    	defer client.Close()
    
    	sub, err := client.SubscriptionAdminClient.CreateSubscription(ctx, &pubsubpb.Subscription{
    		Name:               subscription,
    		Topic:              topic,
    		AckDeadlineSeconds: 10,
    		PushConfig:         &pubsubpb.PushConfig{PushEndpoint: endpoint},
    	})
    	if err != nil {
    		return fmt.Errorf("failed to create push sub: %w", err)
    	}
    	fmt.Fprintf(w, "Created push subscription: %v\n", sub)
    	return nil
    }
    

    Java

    在試用這個範例之前,請先按照快速入門:使用用戶端程式庫中的 Java 設定操作說明進行操作。詳情請參閱 Pub/Sub Java API 參考說明文件

    
    import com.google.cloud.pubsub.v1.SubscriptionAdminClient;
    import com.google.pubsub.v1.PushConfig;
    import com.google.pubsub.v1.Subscription;
    import com.google.pubsub.v1.SubscriptionName;
    import com.google.pubsub.v1.TopicName;
    import java.io.IOException;
    
    public class CreatePushSubscriptionExample {
      public static void main(String... args) throws Exception {
        // TODO(developer): Replace these variables before running the sample.
        String projectId = "your-project-id";
        String subscriptionId = "your-subscription-id";
        String topicId = "your-topic-id";
        String pushEndpoint = "https://my-test-project.appspot.com/push";
    
        createPushSubscriptionExample(projectId, subscriptionId, topicId, pushEndpoint);
      }
    
      public static void createPushSubscriptionExample(
          String projectId, String subscriptionId, String topicId, String pushEndpoint)
          throws IOException {
        try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
          TopicName topicName = TopicName.of(projectId, topicId);
          SubscriptionName subscriptionName = SubscriptionName.of(projectId, subscriptionId);
          PushConfig pushConfig = PushConfig.newBuilder().setPushEndpoint(pushEndpoint).build();
    
          // Create a push subscription with default acknowledgement deadline of 10 seconds.
          // Messages not successfully acknowledged within 10 seconds will get resent by the server.
          Subscription subscription =
              subscriptionAdminClient.createSubscription(subscriptionName, topicName, pushConfig, 10);
          System.out.println("Created push subscription: " + subscription.getName());
        }
      }
    }

    Node.js

    在嘗試這個範例之前,請先按照快速入門:使用用戶端程式庫中的 Node.js 設定說明進行操作。詳情請參閱 Pub/Sub Node.js API 參考說明文件

    /**
     * TODO(developer): Uncomment these variables before running the sample.
     */
    // const pushEndpoint = 'YOUR_ENDPOINT_URL';
    // const topicNameOrId = 'YOUR_TOPIC_NAME_OR_ID';
    // const subscriptionNameOrId = 'YOUR_SUBSCRIPTION_NAME_OR_ID';
    
    // Imports the Google Cloud client library
    const {PubSub} = require('@google-cloud/pubsub');
    
    // Creates a client; cache this for further use
    const pubSubClient = new PubSub();
    
    async function createPushSubscription(
      pushEndpoint,
      topicNameOrId,
      subscriptionNameOrId,
    ) {
      const options = {
        pushConfig: {
          // Set to an HTTPS endpoint of your choice. If necessary, register
          // (authorize) the domain on which the server is hosted.
          pushEndpoint,
        },
      };
    
      await pubSubClient
        .topic(topicNameOrId)
        .createSubscription(subscriptionNameOrId, options);
      console.log(`Subscription ${subscriptionNameOrId} created.`);
    }

    Node.ts

    在嘗試這個範例之前,請先按照快速入門:使用用戶端程式庫中的 Node.js 設定說明進行操作。詳情請參閱 Pub/Sub Node.js API 參考說明文件

    /**
     * TODO(developer): Uncomment these variables before running the sample.
     */
    // const pushEndpoint = 'YOUR_ENDPOINT_URL';
    // const topicNameOrId = 'YOUR_TOPIC_NAME_OR_ID';
    // const subscriptionNameOrId = 'YOUR_SUBSCRIPTION_NAME_OR_ID';
    
    // Imports the Google Cloud client library
    import {PubSub, CreateSubscriptionOptions} from '@google-cloud/pubsub';
    
    // Creates a client; cache this for further use
    const pubSubClient = new PubSub();
    
    async function createPushSubscription(
      pushEndpoint: string,
      topicNameOrId: string,
      subscriptionNameOrId: string,
    ) {
      const options: CreateSubscriptionOptions = {
        pushConfig: {
          // Set to an HTTPS endpoint of your choice. If necessary, register
          // (authorize) the domain on which the server is hosted.
          pushEndpoint,
        },
      };
    
      await pubSubClient
        .topic(topicNameOrId)
        .createSubscription(subscriptionNameOrId, options);
      console.log(`Subscription ${subscriptionNameOrId} created.`);
    }

    PHP

    在試用這個範例之前,請先按照快速入門:使用用戶端程式庫中的 PHP 設定說明進行操作。 詳情請參閱 Pub/Sub PHP API 參考說明文件

    use Google\Cloud\PubSub\PubSubClient;
    
    /**
     * Creates a Pub/Sub push subscription.
     *
     * @param string $projectId  The Google project ID.
     * @param string $topicName  The Pub/Sub topic name.
     * @param string $subscriptionName  The Pub/Sub subscription name.
     * @param string $endpoint  The endpoint for the push subscription.
     */
    function create_push_subscription($projectId, $topicName, $subscriptionName, $endpoint)
    {
        $pubsub = new PubSubClient([
            'projectId' => $projectId,
        ]);
        $topic = $pubsub->topic($topicName);
        $subscription = $topic->subscription($subscriptionName);
        $subscription->create([
            'pushConfig' => ['pushEndpoint' => $endpoint]
        ]);
    
        printf('Subscription created: %s' . PHP_EOL, $subscription->name());
    }

    Python

    在試用這個範例之前,請先按照快速入門:使用用戶端程式庫中的 Python 設定操作說明來進行。詳情請參閱 Pub/Sub Python API 參考說明文件

    from google.cloud import pubsub_v1
    
    # TODO(developer)
    # project_id = "your-project-id"
    # topic_id = "your-topic-id"
    # subscription_id = "your-subscription-id"
    # endpoint = "https://my-test-project.appspot.com/push"
    
    publisher = pubsub_v1.PublisherClient()
    subscriber = pubsub_v1.SubscriberClient()
    topic_path = publisher.topic_path(project_id, topic_id)
    subscription_path = subscriber.subscription_path(project_id, subscription_id)
    
    push_config = pubsub_v1.types.PushConfig(push_endpoint=endpoint)
    
    # Wrap the subscriber in a 'with' block to automatically call close() to
    # close the underlying gRPC channel when done.
    with subscriber:
        subscription = subscriber.create_subscription(
            request={
                "name": subscription_path,
                "topic": topic_path,
                "push_config": push_config,
            }
        )
    
    print(f"Push subscription created: {subscription}.")
    print(f"Endpoint for subscription is: {endpoint}")

    Ruby

    以下範例使用 Ruby Pub/Sub 用戶端程式庫 v3。如果您仍在使用第 2 版程式庫,請參閱 第 3 版遷移指南。如要查看 Ruby 第 2 版程式碼範例清單,請參閱 已淘汰的程式碼範例

    在試用這個範例之前,請先按照快速入門:使用用戶端程式庫的操作說明設定 Ruby 環境。詳情請參閱 Pub/Sub Ruby API 參考說明文件

    # topic_id          = "your-topic-id"
    # subscription_id   = "your-subscription-id"
    # endpoint          = "https://your-test-project.appspot.com/push"
    
    pubsub = Google::Cloud::PubSub.new
    subscription_admin = pubsub.subscription_admin
    
    subscription = subscription_admin.create_subscription \
      name: pubsub.subscription_path(subscription_id),
      topic: pubsub.topic_path(topic_id),
      push_config: {
        push_endpoint: endpoint
      }
    
    puts "Push subscription #{subscription_id} created."

監控推送訂閱

Cloud Monitoring 提供多項指標,可監控訂閱項目

如要查看所有可用的 Pub/Sub 相關指標及其說明,請參閱 Pub/Sub 的監控說明文件

您也可以在 Pub/Sub 中監控訂閱項目。

後續步驟