建立推送訂閱項目

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

事前準備

所需角色和權限

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

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

所需權限

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

  • pubsub.subscriptions.create 專案
  • pubsub.topics.attachSubscription 這個主題

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

跨專案訂閱

如果您在一個專案中為另一個專案的主題建立訂閱項目,您必須對建立訂閱項目的專案具備 pubsub.subscriptions.create 權限,並對主題具備 pubsub.topics.attachSubscription 權限。

推送訂閱項目屬性

推送訂閱項目支援所有常見的訂閱屬性。以下各節說明推送訂閱項目專屬的屬性。

端點

端點網址 (必填):可公開存取的 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 functions 端點位於同一個專案,系統會提供自動驗證和授權機制。

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

  • 目標對象:不區分大小寫的單一字串,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 在虛擬私有雲網路外部運作,無法直接將訊息推送至私人虛擬私有雲位址。不過,您可以使用 Eventarc 將訊息轉送至 VPC 內的服務。Pub/Sub 可將訊息推送至 Eventarc 觸發程序,然後轉送至 VPC 內的服務,例如 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. 在「Pub/Sub topic」(Pub/Sub 主題) 清單中,選取訂閱項目要讀取的主題。

  5. 在「傳送類型」部分,選取「推送」。

  6. 在「端點網址」欄位中輸入端點網址。

  7. 選用:如要啟用驗證功能,請按照下列步驟操作:

    1. 選取「啟用驗證」。
    2. 在「服務帳戶」清單中,選取要用於驗證的服務帳戶。
    3. 選用:在「目標對象」欄位中輸入目標對象。

    詳情請參閱「推送訂閱項目驗證」。

  8. 選用:如要啟用「酬載解除包裝」,請選取「啟用酬載解除包裝」。

    如要在要求標頭中保留訊息中繼資料,請一併選取「寫入中繼資料」。這個選項也會為郵件設定 Content-Type 標頭。

  9. 選用:在「Transforms」(轉換) 部分,新增一或多個單一訊息轉換 (SMT)。詳情請參閱「使用 SMT 建立訂閱項目」。

  10. 選用:在「Filter」(篩選器) 欄位中輸入篩選運算式,篩選訂閱項目中的訊息。詳情請參閱「篩選訂閱內容的訊息」。

  11. 在「重試政策」部分,選取所需選項。詳情請參閱「訂閱重試政策」。

  12. 選用:啟用dead-letter 主題,接收無法傳送的訊息。

    1. 勾選「Dead lettering」核取方塊。

    2. 在「Dead letter topic」(無效信件主題) 清單中,選取或建立無效信件主題。

    3. 在「傳送嘗試次數上限」欄位中,輸入傳送嘗試次數上限。

  13. 選用步驟:在「放送屬性」部分,啟用或停用下列放送選項:

  14. 選用步驟:在「Acknowledgement deadline」(確認期限) 部分,設定訂閱者處理及確認訊息的期限。詳情請參閱「使用租約管理功能延長確認時間」。

  15. 選用步驟:在「Lifetime options」(生命週期選項) 區段中,設定訂閱項目保留訊息的時間長度。

    1. 在「訊息保留時間」部分,指定未確認訊息的保留時間。

    2. 如要保留已確認和未確認的訊息,請勾選「保留已確認訊息」核取方塊。

    詳情請參閱「設定訂閱項目的訊息保留時間」。

  16. 選用:在「有效期限」部分,選取下列任一選項:

    1. 如要設定訂閱項目到期時間,請勾選「Expire after this many days of inactivity」(持續閒置達到指定天數即過期) 核取方塊,輸入訂閱項目可保持閒置的天數,超過這個天數後,Pub/Sub 就會刪除訂閱項目。

    2. 如要停用訂閱到期功能,請選取「永不過期」核取方塊。

    詳情請參閱「訂閱到期」。

  17. 點選「建立」。

你也可以從「主題」部分建立訂閱項目。 這個快速鍵可將主題與訂閱項目建立關聯。

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

    前往「主題」

  2. 按一下要建立訂閱項目的主題旁的 。

  3. 在內容選單中選取「建立訂閱項目」。

  4. 在「Add subscription to topic」(將訂閱項目新增至主題) 頁面中,完成上述程序所述的步驟。系統會自動填入主題 ID。

gcloud

  1. 在 Google Cloud 控制台中啟用 Cloud Shell。

    啟用 Cloud Shell

    Google Cloud 控制台底部會開啟 Cloud Shell 工作階段,並顯示指令列提示。Cloud Shell 是已安裝 Google Cloud CLI 的殼層環境,並已設定適用於您目前專案的值。工作階段可能要幾秒鐘的時間才能初始化。

  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。

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

其中:

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

    {
    "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 Pub/Sub 用戶端程式庫第 3 版。如果您仍在使用第 2 版程式庫,請參閱 第 3 版遷移指南。如要查看 Ruby v2 程式碼範例清單,請參閱 已淘汰的程式碼範例。

    在試用這個範例之前,請先按照「快速入門導覽課程:使用用戶端程式庫」中的 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 內監控訂閱項目。

    後續步驟