Python Stomp.py一次不处理一条消息

Python Stomp.py一次不处理一条消息,python,activemq,stomp,stomp.py,Python,Activemq,Stomp,Stomp.py,我正在使用Stomp.py连接到标准ACtiveMQ服务器。我正在模拟接收器崩溃的情况,我希望能够重新启动它,并在导致它崩溃的消息之后继续从消息运行 我创建了两个示例脚本: putMessagesToQueue.py-这将把56条消息放入 目的地 readMessagesFromQueue.py-这将从中读取消息 目的地。如果它读到第6条消息,它将引发 例外。处理每条消息需要1秒 我运行测试所采取的步骤: 我运行putMessagesToQueue.py 我运行readMessagesFro

我正在使用Stomp.py连接到标准ACtiveMQ服务器。我正在模拟接收器崩溃的情况,我希望能够重新启动它,并在导致它崩溃的消息之后继续从消息运行

我创建了两个示例脚本:

  • putMessagesToQueue.py-这将把56条消息放入 目的地
  • readMessagesFromQueue.py-这将从中读取消息 目的地。如果它读到第6条消息,它将引发 例外。处理每条消息需要1秒
我运行测试所采取的步骤:

  • 我运行putMessagesToQueue.py
  • 我运行readMessagesFromQueue.py-它成功地处理了5条消息,并且在消息6中引发了一个异常
  • 我终止readMessagesFromQueue.py(ctrl-c)
  • 我再次运行readMessagesFromQueue.py
  • 对于我在步骤4中想要的行为,我希望它从消息7开始处理

    但我看不到这一点。 如果Receiver使用ack='auto'订阅,则在步骤4中,它不处理任何消息-所有消息都已从队列中消失,我已丢失50条消息

    如果我使用ack='client'或ack='client-individual',则在步骤4中,它会从头开始,然后在消息6中再次崩溃

    这似乎表明接收者不是一次处理一条消息,而是一次处理每一条消息,并遍历每一条消息。我不希望出现这种行为,因为我想扩大到运行5个接收器,并希望负载分布。此时,我启动的第一个接收者接收了所有的消息,并开始在其中翻滚,2-4个接收者只需等待新消息。我想让接收者一次一条地记录信息

    有谁能给我一些提示,说明我是如何实现这一错误的:

    来源 putMessagesToQueue.py readMessagesFromQueue.py 更新001 通过将接收函数更改为使用ack='client-individual'并手动发送ack消息,我成功地获得了上述所需的行为。(见下文新版本)

    但我仍然无法让接收者一次处理一条消息。这可以通过以下步骤进行演示:

  • 我运行putMessagesToQueue.py
  • 我运行readMessagesFromQueue2.py-它将开始处理
  • 在新的终端中运行readMessagesFromQueue2.py
  • 首先,第二个readMessagesFromQueue2什么也不做,直到第一个崩溃,它才开始接收消息。我希望接收器的两个实例从一开始就读取消息

    readMessagesFromQueue2.py
    大量阅读不同的文档,我发现了问题所在

    ActiveMQ有一个选项预取大小-

    如果您有几封需要长时间处理的邮件,可以将其设置为1。在其他情况下,这不是鸦片

    我可以在stopm.py中使用以下行执行此操作: conn.subscribe(destination=destination,id=1,ack='client-individual',headers={'activemq.prefetchSize':1})


    因此,使用手动或自动确认既不存在也不存在。关键是将预取限制为1。

    更详细。为了实现这一点,我需要prefetchsize=1客户机单个ack,我需要始终发送它们,并在处理消息的长时间运行进程之前发送它们,否则连接可能会重置,导致未知ack errorHi。我们如何确保接收器循环始终运行?我一直收到这样的信息:“接收器循环结束”。请帮忙。从你评论中的信息很难判断。在这个git repo-中,我已经将我对STOMP的使用打包到了一个库中。上次我运行它时,它下面的Stomp client子目录正在工作。
    import stomp
    
    stompurl = "127.0.0.1"
    stompport = "61613"
    stompuser = "admin"
    stomppass = "admin"
    destination = "/queue/testQueueWithCrash"
    
    conn = stomp.Connection(host_and_ports=[(stompurl, stompport)])
    conn.connect(stompuser,stomppass,wait=True)
    
    for x in range(0,5):
      conn.send(body="OK-BEFORE-CRASH", destination=destination)
    
    conn.send(body="CRASH", destination=destination)
    
    for x in range(0,50):
      conn.send(body="OK-AFTER-CRASH", destination=destination)
    
    import stomp
    import time
    
    stompurl = "127.0.0.1"
    stompport = "61613"
    stompuser = "admin"
    stomppass = "admin"
    destination = "/queue/testQueueWithCrash"
    
    conn = stomp.Connection(host_and_ports=[(stompurl, stompport)])
    conn.connect(stompuser,stomppass,wait=True)
    
    class StompConnectionListenerClass(stomp.ConnectionListener):
      processMessage = None
      def __init__(self, processMessage):
        self.processMessage = processMessage
      def on_error(self, headers, message):
        print('XX received an error "%s"' % message)
      def on_message(self, headers, message):
        self.processMessage(headers, message)
    
    def messageProcessingFunction(headers, message):
      print('Main recieved a message "%s"' % message)
      if (message=="CRASH"):
        print("Message told processor to crash")
        raise Exception("Reached message which crashes reciever")
      time.sleep(1) # simulate processing message taking time
    
    stompConnectionListener = StompConnectionListenerClass(processMessage=messageProcessingFunction)
    conn.set_listener('', stompConnectionListener)
    
    print("Subscribing")
    conn.subscribe(destination=destination, id=1, ack='auto')
    #conn.subscribe(destination=destination, id=1, ack='client')
    #conn.subscribe(destination=destination, id=1, ack='client-individual')
    
    print("Terminate loop starting (Press ctrl+c when you want to exit)")
    try:
        while True:
            time.sleep(10)
    except KeyboardInterrupt:
        print('interrupted - so exiting!')
    
    conn.close()
    
    print("Reciever terminated")
    
    import stomp
    import time
    
    stompurl = "127.0.0.1"
    stompport = "61613"
    stompuser = "admin"
    stomppass = "admin"
    destination = "/queue/testQueueWithCrash"
    
    conn = stomp.Connection(host_and_ports=[(stompurl, stompport)])
    conn.connect(stompuser,stomppass,wait=True)
    
    class StompConnectionListenerClass(stomp.ConnectionListener):
      processMessage = None
      conn = None
      def __init__(self, processMessage, conn):
        self.processMessage = processMessage
        self.conn = conn
      def on_error(self, headers, message):
        print('XX received an error "%s"' % message)
      def on_message(self, headers, message):
        try:
          self.processMessage(headers, message)
        finally:
          self.conn.ack(id=headers["message-id"], subscription=headers["subscription"])
    
    def messageProcessingFunction(headers, message):
      print('Main recieved a message "%s"' % message)
      if (message=="CRASH"):
        print("Message told processor to crash")
        raise Exception("Reached message which crashes reciever")
      time.sleep(1) # simulate processing message taking time
    
    stompConnectionListener = StompConnectionListenerClass(processMessage=messageProcessingFunction, conn=conn)
    conn.set_listener('', stompConnectionListener)
    
    print("Subscribing")
    conn.subscribe(destination=destination, id=1, ack='client-individual')
    
    print("Terminate loop starting (Press ctrl+c when you want to exit)")
    try:
        while True:
            time.sleep(10)
    except KeyboardInterrupt:
        print('interrupted - so exiting!')
    
    conn.close()
    
    print("Reciever terminated")