编写和响应 Pub/Sub 消息

区域 ID

REGION_ID 是 Google 根据您在创建应用时选择的区域分配的缩写代码。此代码不对应于国家/地区或省,尽管某些区域 ID 可能类似于常用国家/地区代码和省代码。对于 2020 年 2 月以后创建的应用,REGION_ID.r 包含在 App Engine 网址中。对于在此日期之前创建的现有应用,网址中的区域 ID 是可选的。

详细了解区域 ID

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

本文档介绍如何使用 Cloud Client Library 在 Go 应用中发送和接收 Pub/Sub 消息。

前提条件

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

    克隆示例应用

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

    go get -d -v github.com/GoogleCloudPlatform/golang-samples/pubsub
    cd $GOPATH/src/github.com/GoogleCloudPlatform/golang-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 文件,以为您的主题和验证令牌设置环境变量:

    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: your-token

    代码审核

    示例应用使用 Google Cloud Pub/Sub 客户端库

    示例应用使用您在 app.yaml 文件(PUBSUB_TOPICPUBSUB_VERIFICATION_TOKEN)中设置的环境变量进行配置。

    此实例接收的消息存储在切片中:

    messages   []string
    

    pushHandler 函数接收推送的消息,验证令牌,并将消息添加到 messages 切片:

    
    func pushHandler(w http.ResponseWriter, r *http.Request) {
    	// Verify the token.
    	if r.URL.Query().Get("token") != token {
    		http.Error(w, "Bad token", http.StatusBadRequest)
    		return
    	}
    	msg := &pushRequest{}
    	if err := json.NewDecoder(r.Body).Decode(msg); err != nil {
    		http.Error(w, fmt.Sprintf("Could not decode body: %v", err), http.StatusBadRequest)
    		return
    	}
    
    	messagesMu.Lock()
    	defer messagesMu.Unlock()
    	// Limit to ten.
    	messages = append(messages, string(msg.Message.Data))
    	if len(messages) > maxMessages {
    		messages = messages[len(messages)-maxMessages:]
    	}
    }

    publishHandler 函数向该主题发布新消息。

    
    func publishHandler(w http.ResponseWriter, r *http.Request) {
    	ctx := context.Background()
    
    	msg := &pubsub.Message{
    		Data: []byte(r.FormValue("payload")),
    	}
    
    	if _, err := topic.Publish(ctx, msg).Get(ctx); err != nil {
    		http.Error(w, fmt.Sprintf("Could not publish message: %v", err), 500)
    		return
    	}
    
    	fmt.Fprint(w, "Message published.")
    }

    在本地运行示例

    在本地运行时,您可以借助 Google Cloud CLI 提供身份验证以使用 Google Cloud API。假设您按照前提条件中的说明设置了环境,那么您已经运行了 gcloud init 命令,该命令可提供此身份验证。

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

    export GOOGLE_CLOUD_PROJECT=[your-project-id]
    export PUBSUB_VERIFICATION_TOKEN=[your-token]
    export PUBSUB_TOPIC=[your-topic]
    go run pubsub.go
    

    模拟推送通知

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

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

    curl -H "Content-Type: application/json" -i --data @sample_message.json "localhost:8080/pubsub/push?token=[your-token]"
    

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

    响应:

    HTTP/1.1 200 OK
    Date: Tue, 13 Nov 2018 16:04:18 GMT
    Content-Length: 0
    

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

    在 App Engine 上运行

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

    gcloud app deploy
    

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