Python Rabbitmq多个使用者接收相同的消息,而不是循环
我正在尝试使用rabbitmq延迟消息交换插件,该插件似乎可以很好地发送延迟消息,延迟消息将在延迟间隔后接收。在消费一条消息时,我应该实现通常的循环方法,但我收到的是多个消费者消费同一条消息。客户端函数是我执行basic.consume的地方。它与教程2中关于循环和延迟插件的代码大致相同 代码的工作原理是这样的-receive函数接收一条消息,该消息将以特定的延迟发送回队列中,以便稍后使用。 发送消息延迟发送消息 我面临的问题是basic.consume,由于一些错误配置,我想我会让多个消费者消费相同的消息 我是否需要更改某些内容以实现多个使用者避免处理相同的请求Python Rabbitmq多个使用者接收相同的消息,而不是循环,python,rabbitmq,Python,Rabbitmq,我正在尝试使用rabbitmq延迟消息交换插件,该插件似乎可以很好地发送延迟消息,延迟消息将在延迟间隔后接收。在消费一条消息时,我应该实现通常的循环方法,但我收到的是多个消费者消费同一条消息。客户端函数是我执行basic.consume的地方。它与教程2中关于循环和延迟插件的代码大致相同 代码的工作原理是这样的-receive函数接收一条消息,该消息将以特定的延迟发送回队列中,以便稍后使用。 发送消息延迟发送消息 我面临的问题是basic.consume,由于一些错误配置,我想我会让多个消费者消
class cities:
def __init__(self):
self.connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
self.channel = self.connection.channel()
self.channel.exchange_declare("test-x", type="x-delayed-message", arguments={"x-delayed-type":"direct"})
self.channel.queue_declare(queue='towns_queue')
self.channel.queue_bind(queue="towns_queue", exchange="test-x", routing_key="towns_queue")
self.logger = logging.getLogger("rabbitmq")
self.logger.setLevel(logging.DEBUG)
handler = RotatingFileHandler("logs/Receive.log", maxBytes=100*1024*1024, backupCount=100)
self.logger.addHandler(handler)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
self.errlogger = logging.getLogger("Msg_timer_Error")
self.errlogger.setLevel(logging.ERROR)
errhandler = RotatingFileHandler("logs/towns_error.log", maxBytes=100*1024*1024, backupCount=100)
self.errlogger.addHandler(errhandler)
errformatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
errhandler.setFormatter(errformatter)
def call_api(self,url):
do something
def server_log(self,msg,value):
self.logger.info(msg+" : "+str(value))
def send_msg(self,msg,delay):
try:
delay = delay - 40
self.server_log("Delay Set : ",delay)
delay *=1000
self.channel.basic_publish(exchange='test-x',routing_key='towns_queue',body=msg,properties=pika.BasicProperties(headers={"x-delay"\
:delay},delivery_mode=1))
self.server_log("Msg Sent",msg)
except:
self.errlogger.exception(msg)
self.errlogger.exception(str(traceback.print_exc()))
pass
def receive(self,ch, method, properties, body):
try:
self.server_log("Received message : ",body)
self.process(body)
time.sleep(1)
ch.basic_ack(delivery_tag = method.delivery_tag)
return body
except:
self.errlogger.exception(body)
self.errlogger.exception(str(traceback.print_exc()))
pass
def process(self,body):
delay=self.call_api(body)
if delay:
self.send_msg(body,delay)
def client(self):
try:
self.channel.basic_qos(prefetch_count=1)
self.channel.basic_consume(self.receive,queue='towns_queue',no_ack=False)
self.channel.start_consuming()
except:
self.errlogger.exception(str(traceback.print_exc()))
pass
def close(self):
try:
self.connection.close()
except:
self.errlogger.exception(str(traceback.print_exc()))
pass
def multiprocess(num_process=4):
procs = []
objs = []
for i in range(4):
p = multiprocessing.Process(target=cities().client)
p.start()
procs.append(p)
for p in procs:
p.join()
if __name__ == "__main__":
if len(sys.argv)> 1:
num_proc = sys.argv[1]
if num_proc.isdigit():
num_proc = int(num_proc)
multiprocess(num_proc)
else:
raise Exception ('num_of_processes needs to be an integer.')
else:
multiprocess()
感谢您的帮助
更新:
这可能有问题吗:
def client(self):
try:
self.channel.basic_qos(prefetch_count=1)
self.channel.basic_consume(self.receive,queue='towns_queue',no_ack=False)
self.channel.start_consuming()
except:
self.errlogger.exception(str(traceback.print_exc()))
pass
本教程中的示例为每条消息创建一个新连接。我尝试通过更改send_message函数来实现这一点,在该函数中,我将创建一个新的客户机对象,该对象将创建一个新的连接来发送并在完成后关闭连接。因此,一旦做出了改变,现在它就起作用了
def send_msg(self,msg,delay=0):
try:
newClient=cities(0)
if delay:
delay = delay - 40
self.server_log("Delay Set : ",delay)
delay *=1000
newClient.channel.basic_publish(exchange="test-x",routing_key='towns_queue',body=msg,properties=pika.BasicProperties(headers={"x-delay":delay},delivery_mode=2,))
self.server_log("Msg Sent",msg)
newClient.close()
except:
self.errlogger.exception(msg)
self.errlogger.exception(str(traceback.print_exc()))
pass
此外,还必须更改uu init uuu构造函数,以避免每次都创建记录器,但这不是问题的一部分。教程中的示例为每条消息创建一个新连接。我尝试通过更改send_message函数来实现这一点,在该函数中,我将创建一个新的客户机对象,该对象将创建一个新的连接来发送并在完成后关闭连接。因此,一旦做出了改变,现在它就起作用了
def send_msg(self,msg,delay=0):
try:
newClient=cities(0)
if delay:
delay = delay - 40
self.server_log("Delay Set : ",delay)
delay *=1000
newClient.channel.basic_publish(exchange="test-x",routing_key='towns_queue',body=msg,properties=pika.BasicProperties(headers={"x-delay":delay},delivery_mode=2,))
self.server_log("Msg Sent",msg)
newClient.close()
except:
self.errlogger.exception(msg)
self.errlogger.exception(str(traceback.print_exc()))
pass
此外,还必须更改uuu init uuuuu构造函数,以避免每次都创建记录器,这不是问题的一部分。因此,最初,
receive
get的第一条消息M来自它的towns\u队列中的某个地方,然后如果它检测到延迟(以某种方式)再次发送相同的消息M,然后确认第一条消息M,之后,它将接收第二个M。。。我一定是错过了什么,否则整个事情都在转圈,因为它基本上就是一条永远被转发的消息。尝试为“second M”消息创建一个新的队列/路由键-我认为这不会解决问题,但也许你会看到是否有这个圆..@CantleepNow实际上它应该是一个圆。应该有一个api调用,它将对消息进行一些处理,然后发送一条延迟消息。因此,在api调用确定的延迟之后,相同的消息将完成一些工作。延迟大约在140到2500秒之间。大约有8k条消息,因此需要多个接收器来处理请求。但似乎相同的消息被多个receiversOk接收,那么使用不同的路由密钥发送转发的消息如何?另外,为了测试,你们可以在一条消息中附加一些独特的东西,看看它是否真的只是一条消息而已…@cantSleepNow,我会在某个时候写一个答案。造成的问题是因为我需要在发送一条消息后关闭连接。因此,最初,receive
get的第一条消息M来自它的towns\u队列中的某个地方,然后如果它检测到延迟(以某种方式)再次发送相同的消息M,然后确认第一条消息M,之后它将接收第二条消息M。。。我一定是错过了什么,否则整个事情都在转圈,因为它基本上就是一条永远被转发的消息。尝试为“second M”消息创建一个新的队列/路由键-我认为这不会解决问题,但也许你会看到是否有这个圆..@CantleepNow实际上它应该是一个圆。应该有一个api调用,它将对消息进行一些处理,然后发送一条延迟消息。因此,在api调用确定的延迟之后,相同的消息将完成一些工作。延迟大约在140到2500秒之间。大约有8k条消息,因此需要多个接收器来处理请求。但似乎相同的消息被多个receiversOk接收,那么使用不同的路由密钥发送转发的消息如何?另外,为了测试,你们可以在一条消息中附加一些独特的东西,看看它是否真的只是一条消息而已…@cantSleepNow,我会在某个时候写一个答案。造成的问题是因为我需要在发送消息后关闭连接。