RabbitMQ Producer Connection正在使用Kombu和Pika阻止python中的Consumer

时间:2019-03-11 15:02:10

标签: python rabbitmq uwsgi pika kombu

几天以来,我面临着一个奇怪的问题,我一直在苦苦挣扎。它仅出现在类似“生产”的环境中。这是安装程序:

一个Python 3应用程序,它在一个单独的线程中启动一个队列使用者(仅一个)。连接已在主要过程中建立。该应用程序在kubernetes集群中的高山linux docker映像上与uwsgi和nginx一起运行。 Uwsgi产生5个进程。 (最终在主应用程序的一个线程中有5个使用者)

在我的devbox(仅一个进程)上,一切正常。

有一个生产者将一个工作放在队列中,该工作应该从一个消费者那里获得并获得流程。现在发生以下情况:

  1. 应用程序正在运行,消费者正在等待工作
  2. 我开始制作人
  3. 我将新作品放入队列
  4. 工作在队列中(请检查rabbitmq管理)
  5. 消费者什么都不做
  6. 我辞去了制片人
  7. 消费者什么都不做
  8. 我再次开始制作人
  9. 消费者看到新工作
  10. 需要停止并重新启动生产者,以便消费者完成工作

我开始使用Pika并改用Kombu,因为我坚信这是图书馆问题。但是两者的行为相同。

下面是一些简化的代码,如何编写消费者和生产者:

consumer.py:

import time
from kombu import Connection, BrokerConnection, Exchange, Queue
from kombu.pools import connections
from kombu.mixins import ConsumerMixin



class QueueListenerKombu(ConsumerMixin, threading.Thread):
    queue = None
    connection = None

    def __init__(self, group=None, target=None, name=None, args=(), kwargs=None, *, daemon=None):
        super().__init__(group, target, name, args, kwargs, daemon=daemon)
        self.connection = kwargs.get('connection')
        self.queue = kwargs.get('queue')

    def get_consumers(self, Consumer, channel):
        return [Consumer(queues=self.queue,
                     accept=['json'],
                     callbacks=[self._do_work],
                     prefetch_count=1)]

    def _do_work(self, job_data, message):
        logger.debug("got work")
        message.ack()


class WorkQueueKombu( object ):
    channel = None
    connection = None
    responsequeue_callback = None
    credentials = None
    _queue_listeners = None

    def __init__(self, server="localhost", username="admin", password=""):
        super(WorkQueueKombu, self).__init__()
        self.credentials = {"host": server, "username": username, "password": password, 'port':5672}
        self._connect()
        self._queue_listeners = {}
        self.parameters = None


    def _connect(self):
        connection_string = 'amqp://{username}:{password}@{host}:{port}//'.format(
        username=self.credentials.get('username'),
        password=self.credentials.get('password'),
        host=self.credentials.get('host'),
        port=self.credentials.get('port'))

        self.connection = BrokerConnection(connection_string)

    def _startNewQueueListener(self, queue) -> bool:
        job_exchange = Exchange('alderaanjobs', type='direct')
        job_queues = [Queue(queue, job_exchange, routing_key=queue)]

        listener = QueueListenerKombu( kwargs={"connection":self.connection, "queue": job_queues})
        self._queue_listeners[queue] = listener
        listener.start()

    def start_receiving_work(self, queue):
        self._startNewQueueListener(queue)

这是Publisher.py:

class WorkQueue( object ):
    channel = None
    connection = None

    def __init__(self, server="localhost", username="admin", password=""):
        super(WorkQueue, self).__init__()
        self._connect(server, username, password)
        self._queue_listeners = {}

    def _connect(self, server="localhost", username="admin", password=""):
        connection_string = 'amqp://{username}:{password}@{host}:{port}//'.format(
        username=username,
        password=password,
        host=server,
        port=5672)

        self.connection = BrokerConnection(connection_string)
        self.connection.connect()

    def place_new_work(self, queue, job:dict):
        job_exchange = Exchange('alderaanjobs', type='direct')

        with producers[self.connection].acquire(block=False) as producer:
            producer.publish(job,
                         serializer='json',
                         #compression='bzip2',
                         exchange=job_exchange,
                         declare=[job_exchange],
                         routing_key=queue)

0 个答案:

没有答案