Error “unknown delivery tag” occurs when i try ack messages to RabbitMQ using pika (python)

前端 未结 7 1067
别跟我提以往
别跟我提以往 2021-02-07 00:57

I want process messages in few threads but i\'m getting error during execute this code:

from __future__ import with_statement
import pika
import sys
from pika.ad         


        
7条回答
  •  失恋的感觉
    2021-02-07 01:09

    There is a bug with your code. You share a channel across threads. This is not supported by pika (see FAQ). You have 2 options:

    1. Define the no_ack=True flag in basic_get(...) and do not use the channel object in thread's function doWork(...)
    2. If you need to ACK message only after you have finished your work, then let the main thread (the while True: loop) handle the message ack (and not the worker thread). Below is a modified version of your code that does that.

      from __future__ import with_statement
      import pika
      import sys
      from pika.adapters.blocking_connection import BlockingConnection
      from pika import connection, credentials
      import time
      import threading
      import random
      from pika.adapters.select_connection import SelectConnection
      from pika.connection import Connection
      import traceback
      from Queue import Queue, Empty
      
      def doWork(body, args, channel, ack_queue):
          time.sleep(random.random())
          ack_queue.put(args.delivery_tag)
      
      def doAck(channel):
          while True:
              try:
                  r = ack_queue.get_nowait()
              except Empty:
                  r = None
              if r is None:
                  break
              try:
                  channel.basic_ack(delivery_tag=r)
              except:
                  traceback.print_exc()
      
      auth = credentials.PlainCredentials(username="guest", password="guest")
      params = connection.ConnectionParameters(host="localhost", credentials=auth)
      conn = BlockingConnection(params)
      channel = conn.channel()
      # Create a queue for the messages that should be ACKed by main thread
      ack_queue = Queue()
      
      while True:
          time.sleep(0.03)    
          try:
              doAck(channel)
              method_frame, header_frame, body = channel.basic_get(queue="test_queue")
              if method_frame.NAME == 'Basic.GetEmpty':
                  continue        
              t = threading.Thread(target=doWork, args=[body, method_frame, channel, ack_queue])
              t.setDaemon(True)
              t.start()
          except Exception, e:
              traceback.print_exc()
              continue
      

提交回复
热议问题