跨不同项目设置 pub/sub 订阅?

Setting up pub/sub subscription across different project?

在我的 GCP 项目(项目 A)中,我创建了一个 Pub/sub 主题(topicA)并在其中发布了消息此 pub/sub 主题需要通过订阅 (subscriptionB) 在其他 GCP 项目(项目 B)中使用。

推荐的 subscriptionB 设置方式是什么?

  1. 在项目 A 中定义 subscriptionB 并使用适当的 IAM 权限从项目 B 添加服务帐户。
  2. 在项目 B 中定义 subscriptionB。在云控制台中,可以通过授予 pubsub.topic.attachSubscription 附加来自不同主题的订阅(如下所示)。

方法 2 是否可行?如果是,那么什么时候使用方法 2 以及方法 2 需要做些什么?

第2种方法都可以,还有第3种。

  1. 在项目 B 的服务帐户、项目 A 的订阅(或项目)上使用角色 roles/pubsub.subscriber
  2. 您需要在项目 A 的主题(或项目)上拥有 roles/pubsub.subscriber 角色。如消息中所定义,您至少需要 pubsub.topics.attachSubscription 权限关于主题(或项目)。为此,您可以创建一个 custom role if you want to grant only this permission and not the 2 others of the role roles/pubsub.subscriber
  3. 方案三基于方案一,在项目A中创建一个订阅,但是是Push订阅,将消息推送到一个HTTP端点。本次项目 B 无需身份验证。但是,如果您想保护您的 HTTP 端点(例如部署在 Cloud 运行 或 Cloud Functions 上),您将需要 in the push subscription in the projectA, to have the correct authorization to call the endpoint in projectB
  • A​​ Google Cloud Function 无法通过订阅另一个项目的主题来触发(因为您无法订阅另一个项目的主题)。

  • 但是 Google Cloud Function 可以 发布 到另一个项目的主题(然后将触发该主题的订阅者)。

我通过在原始项目中建立一个 Google Cloud Function 来解决这个问题,它监听原始主题并响应发布到另一个项目中的新主题。因此,这个“中间”功能的服务账号(...@appspot.gserviceaccount.com)需要新主题(console.cloud.google.com/cloudpubsub/topic/detail/...?project=...), 即添加主体角色:“Pub/Sub Publisher

import base64
import json
import os

from google.cloud import pubsub_v1


#https://cloud.google.com/functions/docs/calling/pubsub?hl=en#publishing_a_message_from_within_a_function


# Instantiates a Pub/Sub client
publisher = pubsub_v1.PublisherClient()

def notify(event, context):
    project_id = os.environ.get('project_id')  
    topic_name = os.environ.get('topic_name')  

    # References an existing topic
    topic_path = publisher.topic_path(project_id, topic_name)  

    message_json = json.dumps({
        'data': {'message': 'here would be the message'},  # or you can pass the message of event/context
    })
    message_bytes = message_json.encode('utf-8')

    # Publishes a message
    try:
        publish_future = publisher.publish(topic_path, data=message_bytes)
        publish_future.result()  # Verify the publish succeeded
        return 'Message published.'
    except Exception as e:
        print(e)
        return (e, 500)