GCP Nodejs8云功能-同步PubSub发布

时间:2019-10-09 14:01:07

标签: javascript google-cloud-platform google-api google-cloud-functions google-cloud-pubsub

我正在努力使用javascript / Nodejs8 Google Cloud Function将有效负载发布到Google PubSub。

所以我有一个由HTTP请求触发的Cloud Function,然后将请求主体发布到pubsub主题(配置为拉模式)。

这是我的代码:

const {PubSub} = require('@google-cloud/pubsub');
const pubsub = new PubSub();
const topic = pubsub.topic('my-fancy-topic');

function formatPubSubMessage(reqObj){
    // the body is pure text
    return Buffer.from(reqObj.body);
};

exports.entryPoint = function validate(req, res) {

topic.publish(formatPubSubMessage(req)).then((messageId) => {
            console.log("sent pubsub message with id :: " + messageId)
        });

res.status(200).json({"res":"OK"});
};

我的问题是,在发布pubsub消息之前,云功能完成了执行(在日志中,“我的pubsub日志”之前大约30或40秒出现了“函数执行了X毫秒,状态代码为200”的日志) 。我也有几次带有“忽略已完成功能的异常”的日志,但没有得到pubsub日志)

我不是javascript或nodejs专家,我也不精通javascript promises,但是我想知道是否可以使发布同步。我也在想,我可能在这里做错了!

预先感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

按照您的逻辑,当HTTP消息到达时,将调用回调/事件处理函数。然后,您执行publish()函数。执行发布是异步活动。这意味着发布需要花费一些时间才能完成,并且由于JavaScript(本质上)不想阻塞,因此它会立即返回,并承诺在异步工作完成后可以通知您。在执行publish()之后,您的逻辑立即执行res.status(....),该响应发送对HTTP请求的响应,这实际上是来自HTTP客户端的流请求的结尾。异步发布仍在进行中,当异步发布本身完成时,就会发生发布的回调并记录响应。

不幸的是,这不是Google在此处记录的好习惯...

https://cloud.google.com/functions/docs/bestpractices/tips#do_not_start_background_activities

在最后一个故事中,您调用的validate函数将在完成发布之前结束。如果要在publish()执行时阻塞(有效地使其同步),则可以使用JavaScript await关键字。松散地是这样的:

try {
   let messageId = await topic.publish(....);
   console.log(...);
catch(e) {
 ...
}

您还需要将功能标记为async。例如:

exports.entryPoint = async function validate(req, res) {
   ...

请参阅:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function

您还可以从函数中简单地返回一个Promise,并且直到整个Promise都解决后,回调函数才被视为已解决。

最重要的是深入研究承诺。

答案 1 :(得分:0)

现在,此代码在发布完成之前 发送响应。发送响应后,该功能将终止,正在进行的异步工作可能无法完成。

您应该做的是仅在发布完成后才发送响应,这意味着将代码行放入then回调中。

exports.entryPoint = function validate(req, res) {

    topic.publish(formatPubSubMessage(req)).then((messageId) => {
        console.log("sent pubsub message with id :: " + messageId)
        res.status(200).json({"res":"OK"});
    });

};

我建议花一些时间来学习诺言的工作方式,因为这对于构建可以正常工作的功能至关重要。