问题描述
我正在构建一个在 Cloud Run
上运行的服务,该服务由 PubSub
到 EventArc
触发。
“PubSub”保证至少交付一次,并且会在每个 ackNowledgement
截止日期重试。此截止日期在队列订阅详细信息中设置。
当服务收到发布-订阅请求(在服务中作为 POST 请求接收)时,我们可以在两个点发送回确认。
- 在收到请求后立即开始请求。然后服务将继续按照自己的节奏处理请求。然而,这article指出
在 Cloud Run 上运行的应用完成请求处理后,容器实例对 cpu 的访问将被禁用或受到严重限制。因此,您不应启动在请求处理程序范围之外运行的后台线程或例程。
所以在开始时发送响应可能不是一种选择
- 在服务处理请求之后。因此,这意味着,根据服务将执行的操作,我们无法始终预测处理请求需要多长时间。因此,我们无法正确设置确认截止日期,从而导致 PubSub 重试和重复请求。
那么这里的最佳实践是什么?有没有更好的方法来处理这个问题?
解决方法
由于您担心可能无法设置正确的“确认截止日期”,您可以在代码中使用 modify_ack_deadline()
,如果进程仍在运行,您可以动态延长截止日期。您可以参考此 document 以获取示例代码实现。
请注意 maximum acknowledgement deadline is 600 seconds。只需确保您在云运行中的处理不超过上述限制。
,最佳实践通常是在处理完成后确认消息。除了您链接的 Cloud Run 限制之外,请考虑如果端点在收到消息后立即确认消息,然后在处理该消息时发生错误,您的应用程序可能会丢失该消息。
为了尽量减少重复,您可以将确认期限设置为处理时间的上限。 (如果您的端点最终处理消息的速度比这更快,则 ack 截止时间不会对传入消息进行速率限制。)如果 600 秒的截止时间不够,您可以考虑将消息写入某个持久存储,然后确认它。然后,一个单独的 worker 可以异步处理来自持久存储的消息。
,确认不适用于 Cloud Run,因为确认用于“拉取订阅”,其中进程不断拉取 Cloud PubSub API。
要将事件从 PubSub 获取到 Cloud Run,您可以使用“推送订阅”,即 PubSub 向 Cloud Run 发出 HTTP 请求,然后等待它完成。
在这个推送场景中,PubSub 已经知道它向您发出了一个请求(您收到了事件),因此它不需要关于收到消息的确认。但是,如果您的请求发送了错误的响应代码(例如 http 500),PubSub 将发出另一个重试请求(这可以在推送订阅本身上进行配置)。