编写和响应 Pub/Sub 消息

区域 ID

REGION_ID 是 Google 根据您在创建应用时选择的地区分配的缩写代码。此代码不对应于国家/地区或省,尽管某些地区 ID 可能类似于常用国家/地区代码和省代码。在 App Engine 网址中包含 REGION_ID.r 对于现有应用是可选项,但在不久后将成为所有新应用的必要项。

为了确保顺利过渡,我们正在逐步更新 App Engine 以使用地区 ID。如果我们尚未更新您的 Google Cloud 项目,则您不会看到应用的区域 ID。由于该 ID 对于现有应用是可选的,因此您在现有应用可以使用区域 ID 后无需更新网址或进行其他更改。

详细了解区域 ID

Pub/Sub 可在应用之间提供可靠的多对多异步消息传递服务。发布者应用可以向某一主题发送消息,其他应用可以订阅该主题以接收消息。

本文档介绍如何使用 Cloud 客户端库在 Python 应用中发送和接收 Pub/Sub 消息。

前提条件

  • 按照 App Engine 上的 Python 版“Hello, World!”中的说明设置您的环境和项目,并了解如何构建 App Engine Python 应用。
  • 记下并保存项目 ID,因为您需要用它来运行本文档中所述的示例应用。

克隆示例应用

将示例应用复制到本地机器,然后导航到 pubsub 目录:

git clone https://github.com/GoogleCloudPlatform/python-docs-samples
cd python-docs-samples/appengine/flexible/pubsub

创建主题和订阅

创建主题和订阅,并指定 Pub/Sub 服务器应该向其发送请求的端点:

gcloud pubsub topics create YOUR_TOPIC_NAME
gcloud pubsub subscriptions create YOUR_SUBSCRIPTION_NAME \
    --topic YOUR_TOPIC_NAME \
    --push-endpoint \
    https://YOUR_PROJECT_ID.REGION_ID.r.appspot.com/pubsub/push?token=YOUR_TOKEN \
    --ack-deadline 10

用随机密钥令牌替换 YOUR_TOKEN。推送端点使用它来验证请求。

设置环境变量

修改 app.yaml 文件,为您的项目 ID、主题和验证令牌设置环境变量:

env_variables:
    PUBSUB_TOPIC: your-topic
    # This token is used to verify that requests originate from your
    # application. It can be any sufficiently random string.
    PUBSUB_VERIFICATION_TOKEN: 1234abc

代码审核

示例应用使用 Cloud 客户端库

示例应用使用您在 app.yaml 文件中设置的值来配置环境变量。推送请求处理程序使用这些值来确认请求来自 Pub/Sub 且来源可信:

app.config['PUBSUB_VERIFICATION_TOKEN'] = \
    os.environ['PUBSUB_VERIFICATION_TOKEN']
app.config['PUBSUB_TOPIC'] = os.environ['PUBSUB_TOPIC']

示例应用维护一个全局列表以存储此实例接收的消息:

MESSAGES = []
pubsub_push() 方法接收推送的消息并将其添加到 MESSAGES 全局列表中:

@app.route('/pubsub/push', methods=['POST'])
def pubsub_push():
    if (request.args.get('token', '') !=
            current_app.config['PUBSUB_VERIFICATION_TOKEN']):
        return 'Invalid request', 400

    envelope = json.loads(request.data.decode('utf-8'))
    payload = base64.b64decode(envelope['message']['data'])

    MESSAGES.append(payload)

    # Returning any 2xx status indicates successful receipt of the message.
    return 'OK', 200

index() 方法与 App Engine Web 应用交互,以发布新消息并显示收到的消息:

@app.route('/', methods=['GET', 'POST'])
def index():
    if request.method == 'GET':
        return render_template('index.html', messages=MESSAGES)

    data = request.form.get('payload', 'Example payload').encode('utf-8')

    # publisher = pubsub_v1.PublisherClient()
    topic_path = publisher.topic_path(
        current_app.config['PROJECT'],
        current_app.config['PUBSUB_TOPIC'])

    publisher.publish(topic_path, data=data)

    return 'OK', 200

在本地运行示例

在本地运行示例应用时,您可以通过 Cloud SDK 提供身份验证,以使用 Google Cloud API。如果您按照前提条件中的说明设置了环境,则 gcloud init 命令应该已在运行并可提供此身份验证。

安装依赖项(最好在虚拟环境中)。

Mac OS/Linux

  1. 在项目以外的目录中创建一个独立的 Python 环境并将其激活:
    python3 -m venv env
    source env/bin/activate
  2. 导航到项目目录并安装依赖项:
    cd YOUR_PROJECT
    pip install  -r requirements.txt

Windows

使用 Powershell 运行 Python 软件包。

  1. 找到已安装的 Powershell
  2. 右键点击 Powershell 的快捷方式,并以管理员身份启动。
  3. 在项目以外的目录中创建一个独立的 Python 环境并将其激活:
    python -m venv env
    env\Scripts\activate
  4. 导航到项目目录并安装依赖项:
    cd YOUR_PROJECT
    pip install -r requirements.txt

然后在启动应用之前设置环境变量:

export GOOGLE_CLOUD_PROJECT=[your-project-id]
export PUBSUB_VERIFICATION_TOKEN=[your-verification-token]
export PUBSUB_TOPIC=[your-topic]
python main.py

模拟推送通知

应用可以在本地发送消息,但无法在本地接收推送消息。但是,您可以向本地推送通知端点发送 HTTP 请求来模拟推送消息。该示例包含文件 sample_message.json

您可以使用 curlhttpie 客户端发送 HTTP POST 请求:

curl -i --data @sample_message.json "localhost:8080/push-handlers/receive_messages?token=[your-token]"

http POST ":8080/push-handlers/receive_messages?token=[your-token]" < sample_message.json

响应:

HTTP/1.0 200 OK
Content-Length: 2
Content-Type: text/html; charset=utf-8
Date: Mon, 10 Aug 2015 17:52:03 GMT
Server: Werkzeug/0.10.4 Python/2.7.10

OK

请求完成后,您可以刷新 localhost:8080 并在收到的消息列表中查看该消息。

在 App Engine 上运行

如需使用 gcloud 命令行工具将演示应用部署到 App Engine,请从 app.yaml 文件所在的目录运行以下命令:

gcloud app deploy

您现在可以通过 https://PROJECT_ID.REGION_ID.r.appspot.com 访问该应用。您可以使用表单提交消息,但无法保证您的哪个应用实例会收到通知。您可以发送多条消息并刷新页面,以查看收到的消息。