几天以来,我面临着一个奇怪的问题,我一直在苦苦挣扎。它仅出现在类似“生产”的环境中。这是安装程序:
一个Python 3应用程序,它在一个单独的线程中启动一个队列使用者(仅一个)。连接已在主要过程中建立。该应用程序在kubernetes集群中的高山linux docker映像上与uwsgi和nginx一起运行。 Uwsgi产生5个进程。 (最终在主应用程序的一个线程中有5个使用者)
在我的devbox(仅一个进程)上,一切正常。
有一个生产者将一个工作放在队列中,该工作应该从一个消费者那里获得并获得流程。现在发生以下情况:
我开始使用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)