为什么我们的 GCP Cloud Function 从其 PubSub 订阅中收到如此多的重复项?

Why does our GCP Cloud Function receive so many duplicates from its PubSub subscription?

简而言之

有一个 Google Cloud PubSub 主题,我们向其发布了 2M tiny/small 条消息。我们设置了一个 Cloud Functions 来处理来自该主题的消息。在检查日志时,我们看到很多这些消息被处理了多次。总而言之,我们有 150-200% 的消息传出数量(见最后的截图)。

问题是:这是为什么?我们如何正确配置事物以减少重复?

附加信息

更新 15.03.22

所以我想绝对确定这是“真正的”重复,我的意思是它是 PubSub 多次交付 messages/events,而不是我们在某处笨拙地引入的重复。所以我修改了我们的函数代码,从我们的外部消息 ID 和 context.messageId 形成一个 Datastore 键,并用一个计数器将它写入 Datastore。如果密钥已经存在,则计数器会递增。紧接着我记录了实体。以下是 458,940 次处决的统计数据:

|-------------------|-------------------|
|      Counter      |       Logs        |
|-------------------|-------------------|
|         1         |       208,733     |
|         2         |       101,040     |
|         3         |       62,965      |
|         4         |       37,156      |
|         5         |       20,583      |
|         >5        |       28,463      |
|         >15       |       20          |
|         >20       |       0           |
|-------------------|-------------------|

我唯一的(糟糕的)领导

我现在唯一的理论是,重复是由于底层基础设施由于实例限制而以 429 响应造成的。请参阅以下屏幕截图。

我们不再真正注意到这一点,因为我们只是通过过滤 log_name 在日志控制台中过滤掉相应的日志消息,因为基础设施抛出大量警告和错误似乎是预期的行为。这就是为什么我也怀疑这是重复的原因。另一方面,看起来基础设施确实可以在这些情况下发送 NACK。

尽管感觉预期的行为是原始消息的传递失败并显示 429(但未显示在我们的日志中),然后重新传递,可能是重复的。这不是我们观察到的,我们的日志确实显示重复执行。

所以我完全不确定这是一个有前途的领先优势,但这就是我现在得到的全部。

其他资源

我觉得我们正在观察的内容听起来与 and the docs here 中描述的内容相似,但这是关于“StreamingPull”订阅的,而 GCF 管理的订阅似乎是(特殊的?)“推送”订阅。一开始我很兴奋,因为听起来很像,但似乎不适用。

屏幕截图

显示主题之间消息重复的屏幕截图:

订阅配置(由 GCF 管理):

429’s errors are happening because there are too many requests or there is too much traffic with the instances. Also, your maximum Instances are 90, the suggested default is 3000.

此外,如果您不想有任何限制,您可以清除最大实例数或将其设置为 0。另一方面,您可以添加一个更高的最大实例数,从 90 到 180,最后再增加一点,以解决 429 错误的问题。

在您的订阅中可能导致此重复行为的其他因素是:

  • 订阅者队列中的消息未被处理和确认 在截止日期内;

  • 客户端库继续(自动)延长截止日期 希望最终能够处理这些消息;

  • 在某些时候,在几个截止日期延长后客户端库 放弃,因此这些消息将被丢弃并重新传送;

  • Pub/Sub中的消息是分批发送的,所以不仅是过期的 消息将被重新传递,但属于这些的消息也会被重新传递 消息的批次;

  • 订阅者的队列将充满重复项,这会减慢速度 减少积压消耗;

  • 问题变得越来越严重,因为当前的重复项会 也会过期并生成新的副本。