简体   繁体   English

Pub/Sub 测试:即使通过了 ack_deadline,客户端也会收到消息

[英]Pub/Sub testing: message received by client even when ack_deadline is passed

I'm testing Cloud Pub/Sub.我正在测试 Cloud Pub/Sub。 According to google documentation, ack_deadline of a pull substription can be set between 10s-600s ie.根据 google 文档,拉取子条的ack_deadline可以设置在 10s-600s 之间,即。 msg will be redelivered by Pubsub if ack_deadline is passed.如果通过了 ack_deadline,则消息将由ack_deadline重新传递。

I'm processing the pubsub message in subscriber client before ack-ing the msg.在确认消息之前,我正在订阅者客户端中处理 pubsub 消息。 This processing time can take ~ 700s which exceeds the max limit of 600s.此处理时间可能需要约 700 秒,超过了 600 秒的最大限制。

reproduction:再生产:

  1. create a topic and subscription (by default Acknowledgement deadline is set to 10s)创建主题和订阅(默认确认截止日期设置为 10 秒)
  2. run subscriber code (which ack the messages) see below运行订阅者代码(确认消息)见下文
  3. publish some msg on the topic from Web UI从 Web UI 发布一些关于该主题的消息

subscriber code:订阅者代码:

import time
import datetime
from concurrent.futures import TimeoutError
from google.cloud import pubsub_v1


project_id = "my-project"
subscription_id = "test-sub"
def sub():

    subscriber = pubsub_v1.SubscriberClient()
    subscription_path = subscriber.subscription_path(project_id, subscription_id)

    def callback(message: pubsub_v1.subscriber.message.Message) -> None: 
        # My processing code, which takes 700s
        time.sleep(700) # sleep function to demonstrate processing 
        print(f"Received {message}."+ str(datetime.datetime.now()) )
        message.ack()
        print("msg acked")

    streaming_pull_future = subscriber.subscribe(subscription_path, callback=callback)
    print(f"Listening for messages on {subscription_path}..\n")

    try:
        streaming_pull_future.result()
    except:  
        streaming_pull_future.cancel()  # Trigger the shutdown.
        streaming_pull_future.result()  # Block until the shutdown is complete.

    subscriber.close()
       
if __name__ == "__main__":
    sub()

Even if the ack_deadline is reached, the message is getting acked which is weird.即使到达ack_deadline ,消息也会被确认,这很奇怪。 According to my understanding, pubsub should redeliver the message again and eventually go this code will go into an infinite loop.根据我的理解,pubsub 应该再次重新传递消息,最终 go 这段代码将 go 进入无限循环。

am I missing something here?我在这里错过了什么吗?

That's correct.这是正确的。 There are several solutions with their tradeoff有几种解决方案与它们的权衡

  • Ack immediately the message and process it.立即确认消息并处理它。 The problem is: if you have an outage on your system, you lost the message问题是:如果您的系统出现中断,您就会丢失消息
  • Save the message ID state in a database (firestore for instance).将消息 ID state 保存在数据库(例如 Firestore)中。
    • If the message ID is new, start the processing;如果消息ID是新的,则开始处理; at the end of the processing update the message ID status in the database在处理结束时更新数据库中的消息 ID 状态
    • If the message ID already exists, sleep a while (about 90s), check the status of the message ID in the database.如果消息ID已经存在,休眠一段时间(大约90s),查看数据库中消息ID的状态。 If DONE, ack the message.如果完成,确认消息。 If not, sleep again (max 6 time. Then NACK and start again that process. To break the loop, repeat the process until the message timestamp is above 1h)如果不是,请再次休眠(最多 6 次。然后 NACK 并重新开始该过程。要中断循环,请重复该过程,直到消息时间戳高于 1 小时)
  • Save the message in database, ack the message, and start the processing.将消息保存在数据库中,确认消息,然后开始处理。 In case of outage, at the start, check the not yet done messages and restart the process for each of them.在中断的情况下,在开始时,检查尚未完成的消息并为每个消息重新启动进程。 At the end of the process, mark them as DONE.在该过程结束时,将它们标记为 DONE。

You can also imagine other pattern.您还可以想象其他模式。 nothing is real perfect, depends on your needs.没有什么是真正完美的,取决于您的需求。

The reason that the message is getting acked and not getting redelivered even after the ack deadline specified in the subscription is reached is that the Pub/Sub client libraries internally extend ack deadlines up to a time specified when instantiating the subscriber client.即使在达到订阅中指定的确认截止日期之后,消息也得到确认并且没有重新传递的原因是 Pub/Sub 客户端库在内部将确认截止日期延长到实例化订阅者客户端时指定的时间。 By default, the time is 1 hour.默认情况下,时间为 1 小时。 You can change this amount of time by changing the max_lease_duration parameter in the FlowControl object (search for "FlowControl" in the Types page ) passed into the subscribe method .您可以通过更改传入subscribe方法FlowControl object(在“ 类型”页面中搜索“FlowControl”)中的max_lease_duration参数来更改此时间量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何修改 GCP Pub/Sub 上推送订阅消息的确认截止日期? - How to modify ack deadline for a push subscription message on GCP Pub/Sub? 即使将确认截止日期设置为 600 秒,Pub/Sub 也会在 10 秒后重新发送消息。 如何克服这个问题? - Pub/Sub re-sending message after 10 sec even setting ack deadline 600 sec. How to overcome this issue? Dataflow Pub/Sub 流作业卡住并不断修改消息的 ACK 截止日期 - Dataflow Pub/Sub streaming jobs get stuck and keep modifying ACK deadline of messages 在 pub sub 上发布消息时调用 google cloud http function - Invoke google cloud http function when message publish on a pub sub BigQuery 可以发送发布/订阅消息吗? - Can BigQuery send a pub/sub message? Google Cloud Pub/Sub 按 ID 检索消息 - Google Cloud Pub/Sub retrieve message by ID Google Cloud Pub/Sub C++ 客户端:二进制文件具有 setuid(root)时身份验证失败 [CentOS7] - Google Cloud Pub/Sub C++ Client: Authentication Failure When Binary Has setuid (root) [CentOS7] Apache beam 似乎正在截断 pub sub 消息有效负载 - Apache beam seems to be truncating pub sub message payload 客户端库中基于全局的流控制发布/订阅 - Flow control pub/sub on global basis in client library 是否可以为 eventarc pubsub 订阅设置 ACK 截止日期? - Is it possible to set ACK deadline for an eventarc pubsub subscription?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM