创建推送订阅

本文档介绍了如何创建推送订阅。您可以使用 Google Cloud 控制台、Google Cloud CLI、客户端库或 Pub/Sub API 创建推送订阅。

准备工作

所需的角色和权限

如需创建订阅,您必须在项目级层配置访问权限控制。如果您的订阅和主题位于不同的项目中,您还需要拥有资源级权限,如本部分后面所述。

如需获得创建推送订阅所需的权限,请让您的管理员向您授予项目的 Pub/Sub Editor (roles/pubsub.editor) IAM 角色。 如需详细了解如何授予角色,请参阅管理对项目、文件夹和组织的访问权限

此预定义角色包含创建推送订阅所需的权限。如需查看所需的确切权限,请展开所需权限部分:

所需权限

创建推送订阅需要以下权限:

  • 创建订阅: 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 Editor (roles/pubsub.editor) IAM 角色。

推送订阅属性

配置推送订阅时,您可以指定以下属性。

通用属性

了解您可以在所有订阅中设置的常见订阅属性

端点

端点网址(必需)。可公开访问的 HTTPS 地址。推送端点的服务器必须具有由证书授权机构签署的有效 SSL 证书。Pub/Sub 服务会将同一 Google Cloud 地区中的消息传送至 Pub/Sub 服务存储消息所在的推送端点。Pub/Sub 服务会尽最大努力传送来自同一 Google Cloud 地区的消息。

Pub/Sub 不再要求证明对推送订阅网址网域的所有权。如果您的网域收到来自 Pub/Sub 的意外 POST 请求,您可以举报疑似滥用行为

身份验证

启用身份验证。启用后,Pub/Sub 传送到推送端点的消息会包含授权标头,以允许端点对请求进行身份验证。如果 App Engine 标准应用和 Cloud Run 函数端点托管在订阅所属的项目中,则可以使用自动身份验证和授权机制。

经过身份验证的推送订阅的身份验证配置包括一个用户代管式服务账号,以及在 createpatchModifyPushConfig 调用中指定的受众群体参数。您还必须向服务代理授予特定角色,如下一部分所述。

  • 代管式服务账号(必需)。与推送订阅关联的服务账号。此账号将用作生成的 JSON Web 令牌 (JWT) 的 email 声明。以下是服务账号的要求列表:

  • 观众。一个不区分大小写的字符串,供 Webhook 用于验证此特定令牌的目标受众群体。

  • 服务代理(必需)。

    • Pub/Sub 会自动为您创建一个格式为 service-{PROJECT_NUMBER}@gcp-sa-pubsub.iam.gserviceaccount.com 的服务账号。

    • 必须向此服务代理授予 iam.serviceAccounts.getOpenIdToken 权限(包含在 roles/iam.serviceAccountTokenCreator 角色中),以允许 Pub/Sub 为经过身份验证的推送请求创建 JWT 令牌。

载荷解封

启用载荷解封选项会剥离 Pub/Sub 消息中的所有消息元数据(消息数据除外)。通过载荷展开,消息数据会直接作为 HTTP 正文传送。

  • 写入元数据。将之前移除的消息元数据重新添加到请求标头中。

VPC Service Controls

对于受 VPC Service Controls 保护的项目,请注意推送订阅存在以下限制:

  • 您只能创建将推送端点设置为使用默认 run.app 网址的 Cloud Run 服务或 Workflows 执行的新推送订阅。自定义网域不起作用。

  • 通过 Eventarc 将事件路由到推送端点设置为 Workflows 执行的 Workflows 目标时,您只能通过 Eventarc 创建新的推送订阅。

  • 您无法更新现有的推送订阅。这些推送订阅会继续运行,但不受 VPC Service Controls 的保护。

创建推送订阅

以下示例演示了如何使用提供的默认设置创建使用推送传送的订阅。

默认情况下,订阅使用拉取传送,除非您明确设置了推送配置,如以下示例所示。

控制台

如需创建推送订阅,请完成以下步骤:

  1. 在 Google Cloud 控制台中,前往订阅页面。

    前往“订阅”页面

  2. 点击创建订阅
  3. 订阅 ID 字段中,输入名称。

    如需了解如何命名订阅,请参阅主题或订阅命名指南

  4. 从下拉菜单中选择或创建一个主题。订阅将接收来自该主题的消息。
  5. 传送类型选择为推送
  6. 指定端点网址。
  7. 保留所有其他默认值。
  8. 点击创建

您还可以通过主题部分创建订阅。此快捷方式可帮助您将主题与订阅关联。

  1. 在 Google Cloud 控制台中,前往主题页面。

    转到“主题”

  2. 点击要创建订阅的主题旁边的
  3. 从上下文菜单中,选择创建订阅
  4. 输入订阅 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

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#

    在尝试此示例之前,请按照 Pub/Sub 快速入门:使用客户端库中的 C# 设置说明进行操作。 如需了解详情,请参阅 Pub/Sub C# API 参考文档

    如需向 Pub/Sub 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为客户端库设置身份验证

    
    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

    在尝试此示例之前,请按照 Pub/Sub 快速入门:使用客户端库中的 Go 设置说明进行操作。 如需了解详情,请参阅 Pub/Sub Go API 参考文档

    如需向 Pub/Sub 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为客户端库设置身份验证

    import (
    	"context"
    	"fmt"
    	"io"
    	"time"
    
    	"cloud.google.com/go/pubsub"
    )
    
    func createWithEndpoint(w io.Writer, projectID, subID string, topic *pubsub.Topic, endpoint string) error {
    	// projectID := "my-project-id"
    	// subID := "my-sub"
    	// topic of type https://godoc.org/cloud.google.com/go/pubsub#Topic
    	// 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.CreateSubscription(ctx, subID, pubsub.SubscriptionConfig{
    		Topic:       topic,
    		AckDeadline: 10 * time.Second,
    		PushConfig:  pubsub.PushConfig{Endpoint: endpoint},
    	})
    	if err != nil {
    		return fmt.Errorf("CreateSubscription: %w", err)
    	}
    	fmt.Fprintf(w, "Created push subscription: %v\n", sub)
    	return nil
    }
    

    Java

    在尝试此示例之前,请按照 Pub/Sub 快速入门:使用客户端库中的 Java 设置说明进行操作。 如需了解详情,请参阅 Pub/Sub Java API 参考文档

    如需向 Pub/Sub 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为客户端库设置身份验证

    
    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

    /**
     * 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.js

    /**
     * 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

    在尝试此示例之前,请按照 Pub/Sub 快速入门:使用客户端库中的 PHP 设置说明进行操作。 如需了解详情,请参阅 Pub/Sub PHP API 参考文档

    如需向 Pub/Sub 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为客户端库设置身份验证

    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

    在尝试此示例之前,请按照 Pub/Sub 快速入门:使用客户端库中的 Python 设置说明进行操作。 如需了解详情,请参阅 Pub/Sub Python API 参考文档

    如需向 Pub/Sub 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为客户端库设置身份验证

    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 快速入门:使用客户端库中的 Ruby 设置说明进行操作。 如需了解详情,请参阅 Pub/Sub Ruby API 参考文档

    如需向 Pub/Sub 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为客户端库设置身份验证

    # topic_id          = "your-topic-id"
    # subscription_id   = "your-subscription-id"
    # endpoint          = "https://your-test-project.appspot.com/push"
    
    pubsub = Google::Cloud::Pubsub.new
    
    topic        = pubsub.topic topic_id
    subscription = topic.subscribe subscription_id,
                                   endpoint: endpoint
    
    puts "Push subscription #{subscription_id} created."

    监控推送订阅

    Cloud Monitoring 提供了一些指标来监控订阅

    如需查看与 Pub/Sub 相关的所有可用指标及其说明的列表,请参阅 Pub/Sub 监控文档

    您还可以在 Pub/Sub 中监控订阅。

    后续步骤