跨不同项目设置 pub/sub 订阅?
Setting up pub/sub subscription across different project?
在我的 GCP 项目(项目 A)中,我创建了一个 Pub/sub 主题(topicA)并在其中发布了消息此 pub/sub 主题需要通过订阅 (subscriptionB) 在其他 GCP 项目(项目 B)中使用。
推荐的 subscriptionB 设置方式是什么?
- 在项目 A 中定义 subscriptionB 并使用适当的 IAM 权限从项目 B 添加服务帐户。
- 在项目 B 中定义 subscriptionB。在云控制台中,可以通过授予 pubsub.topic.attachSubscription 附加来自不同主题的订阅(如下所示)。
方法 2 是否可行?如果是,那么什么时候使用方法 2 以及方法 2 需要做些什么?
第2种方法都可以,还有第3种。
- 在项目 B 的服务帐户、项目 A 的订阅(或项目)上使用角色
roles/pubsub.subscriber
- 您需要在项目 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
- 方案三基于方案一,在项目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)
在我的 GCP 项目(项目 A)中,我创建了一个 Pub/sub 主题(topicA)并在其中发布了消息此 pub/sub 主题需要通过订阅 (subscriptionB) 在其他 GCP 项目(项目 B)中使用。
推荐的 subscriptionB 设置方式是什么?
- 在项目 A 中定义 subscriptionB 并使用适当的 IAM 权限从项目 B 添加服务帐户。
- 在项目 B 中定义 subscriptionB。在云控制台中,可以通过授予 pubsub.topic.attachSubscription 附加来自不同主题的订阅(如下所示)。
方法 2 是否可行?如果是,那么什么时候使用方法 2 以及方法 2 需要做些什么?
第2种方法都可以,还有第3种。
- 在项目 B 的服务帐户、项目 A 的订阅(或项目)上使用角色
roles/pubsub.subscriber
- 您需要在项目 A 的主题(或项目)上拥有
roles/pubsub.subscriber
角色。如消息中所定义,您至少需要pubsub.topics.attachSubscription
权限关于主题(或项目)。为此,您可以创建一个 custom role if you want to grant only this permission and not the 2 others of the roleroles/pubsub.subscriber
- 方案三基于方案一,在项目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)