我们有一个使用2个pubsub主题/订阅对的架构:
T1
由cronjob定期触发(例如每5分钟)。订阅S1
是我们云功能的触发器。T2
充当由我们的某个服务发布的后台作业的队列。每次执行时,云功能都会读取订阅S2
,以便为排队的后台作业提供服务。这使我们可以控制后台作业的服务频率,而不管它们何时被添加到队列中。
云功能(由S1
触发)通过pulling从S2
读取消息。它决定哪些后台作业准备就绪,并在成功为作业提供服务后,确认相关消息。未准备好或失败的作业不会被确认以后再进行维修。
我们在使用Google官方node.js pubusb client时遇到问题:
ack()
。S2
中排队。我们认为谷歌的node.js pubsub客户端存在问题。云功能文档明确指出not start background activities。但是,查看node.js pubsub客户端源,它显然使用超时在后台提供确认。
谷歌的node.js pubsub客户端与谷歌云功能不兼容吗? Google recommends accessing the service API's only when a client library does not exist or does not meet other needs。是否在云功能“其他需求”中运行客户端,要求我们使用服务API编写自己的客户端?
作为“解决方法”,我们尝试延迟执行云功能以允许node.js pubsub客户端中的任何“后台”进程完成,但这并不能始终如一地消除我们的问题。似乎pubsub客户端不是云功能友好的,无法在云功能执行之间停止恢复。
我写了an article on our blog,详细描述了为什么我们以这种方式使用PubSub以及我们如何处理node.js pubsub客户端与云功能不兼容的事实。 / p>
答案 0 :(得分:1)
你是如何触发你的职能的?
根据docs,如果你的函数正在使用pubsub消息,那么你应该使用pubsub触发器。使用pubsub触发器时,不需要库。只需在函数末尾调用callback()
,即可正确确认pubsub消息。
对于您打算做的事情,我认为您当前的架构不是正确的选择。
我会使用cron task将您的第一步移至Google App Engine,并使此任务只是将消息从T2
移至T1
,使该函数具有触发器{{1并处理消息。
因此,您的工作将在S2
上发布,并且您有一个由cron任务触发的拉取订阅T2
的GAE应用,此应用会重新发布该消息S2
。然后,您的函数将由订阅T1
到主题S1
触发,并将在消息中运行该作业,从而避免导入pubsub库的额外处理,并按预期使用该产品。 / p>
此外,我不确定您最初是如何将作业发布到该主题的,但Task Queues是速率限制任务的良好GAE(和product-agnostic in Alpha)选项。
仅用于此的GAE应用程序(设置1个最大实例)将在always free limit内,因此成本不会显着增加。
答案 1 :(得分:1)
来自node.js pubsub客户端confirmed的开发人员使用客户端从云功能中提取消息不是受支持的用例。
另一种方法是使用service APIs。但是,尝试从订阅中提取所有消息时,REST API有their own caveats。
答案 2 :(得分:0)
我遇到了同样的问题,我想更好地控制.ack()
。查看Google的nodejs库,可以选择重构ack()
以返回诺言,以便函数可以等待ack()
完成。
Subscriber.prototype.ack_ = function(message) {
var breakLease = this.breakLease_.bind(this, message);
this.histogram.add(Date.now() - message.received);
if (this.writeToStreams_ && this.isConnected_()) {
this.acknowledge_(message.ackId, message.connectionId).then(breakLease);
return;
}
this.inventory_.ack.push(message.ackId);
this.setFlushTimeout_().then(breakLease);
};