[英]RabbitMQ Python Pika - Connection handling for multiple messages
[英]RabbitMq - pika - python - Dropping messages when published
def get_connection_and_channel(self, connection_parameters):
connection = pika.BlockingConnection(connection_parameters)
channel = connection.channel()
return (connection, channel)
connection_parameters = pika.ConnectionParameters( server, port, virtual_host, credentials=pika.PlainCredentials(user_name, password))
connection,channel = self.get_connection_and_channel(connection_parameters)
channel.confirm_delivery()
count=0
for json_string in open(json_file, 'r'):
result_json = json.loads(json_string)
message_body = json.dumps(result_json['body'])
routing_key = result_json['RoutingKey']
channel.basic_publish(exchange=self.output_exchange_name,routing_key=routing_key,body=message_body.strip())
count += 1
self.logger.info('Sent %d messages' % count)
connection.close()
我正在使用此代碼將消息發送到RabbitMQ服務器。 但偶爾這不會將所有消息發送到相應的隊列。 它每次運行時都會丟失隨機數量的消息。
我無法理解這里的問題是什么。
有可能是您的消息被返回,因為它無法將消息路由到任何現有隊列。 嘗試在channel.confirm_delivery
添加回調:
channel.confirm_delivery(on_delivery_confirmation)
def on_delivery_confirmation(self, method_frame):
confirmation_type = method_frame.method.NAME.split('.')[1].lower()
if confirmation_type == 'ack':
self.logger.info('message published')
elif confirmation_type == 'nack':
self.logger.info('message not routed')
如果是這種情況,則在發布消息之前嘗試首先使用交換和路由密鑰綁定使用者隊列。
首先,啟用持久隊列添加:
channel.queue_declare(queue='your_queue', durable=True)
發布者和消費者 (在進行發布/消費之前) 。
然后,即使RabbitMQ服務器死機並重新啟動,您也可以確保您的隊列不會丟失。
在發布者上,將properties=pika.BasicProperties(delivery_mode=2)
到您的basic_publish
調用中,以確保您的消息是持久的。
channel.basic_publish(exchange=self.output_exchange_name,
routing_key=routing_key,
body=message_body.strip(),
properties=pika.BasicProperties(delivery_mode=2))
這應該可以避免丟失_published消息。
從消費者的角度來看, python的官方RabbitMQ教程說:
為了確保消息永不丟失,RabbitMQ支持消息確認。 從消費者發回ack(nowledgement)以告知RabbitMQ已收到,處理了特定消息,並且RabbitMQ可以自由刪除它。 [...]默認情況下會啟用消息確認。
構建使用者時,確保正確發送ack ,讓RabbitMQ將其從隊列中刪除。
def callback(ch, method, properties, body):
print "Received %r" % (body,)
ch.basic_ack(delivery_tag = method.delivery_tag)
channel.basic_consume(callback, queue='your_queue')
如果您需要一種更強大,更可靠的方法來完全確定在RabbitMQ上發布確認中繼,您應該使用AMQP協議的plublish confirm功能。
來自pika文件 :
import pika
# Open a connection to RabbitMQ on localhost using all default parameters
connection = pika.BlockingConnection()
# Open the channel
channel = connection.channel()
# Declare the queue
channel.queue_declare(queue="test", durable=True, exclusive=False, auto_delete=False)
# Turn on delivery confirmations
channel.confirm_delivery()
# Send a message
if channel.basic_publish(exchange='test',
routing_key='test',
body='Hello World!',
properties=pika.BasicProperties(content_type='text/plain',
delivery_mode=1)):
print 'Message publish was confirmed'
else:
print 'Message could not be confirmed'
所以根據你的代碼,我將使用類似的東西:
count=0
for json_string in open(json_file, 'r'):
result_json = json.loads(json_string)
message_body = json.dumps(result_json['body'])
routing_key = result_json['RoutingKey']
if channel.basic_publish(exchange=self.output_exchange_name,routing_key=routing_key,body=message_body.strip(),
properties=pika.BasicProperties(delivery_mode=2)): # Make it persistent
count += 1
else:
# Do something with your undelivered message
self.logger.info('Sent %d messages' % count)
connection.close()
或者作為一種強力方法,您可以使用while
循環而不是if
來確保發送所有消息:
count = 0
for json_string in open(json_file, 'r'):
result_json = json.loads(json_string)
message_body = json.dumps(result_json['body'])
routing_key = result_json['RoutingKey']
while not channel.basic_publish(exchange=self.output_exchange_name,
routing_key=routing_key,
body=message_body.strip(),
properties=pika.BasicProperties(delivery_mode=2)):
pass # Do nothing or even you can count retries
count += 1
self.logger.info('Sent %d messages' % count)
嘗試使用您的命令只接收一條消息:
#!/usr/bin/env python
import pika
import ujson as json
def receive():
parameters = pika.ConnectionParameters(host='localhost')
connection = pika.BlockingConnection(parameters)
channel = connection.channel()
channel.queue_declare(queue='raw_post', durable=True)
method_frame, header_frame, body = channel.basic_get(queue='raw_post')
if method_frame.NAME == 'Basic.GetEmpty':
connection.close()
return ''
else:
channel.basic_ack(delivery_tag=method_frame.delivery_tag)
connection.close()
return json.loads(body), method_frame.message_count
a = ''
while a not in ['quit', 'sair', 'exit', 'bye']:
a = input("whats up?")
print(receive())
只有一個發送者有5000條消息要排隊:
#!/usr/bin/env python
import pika
import ujson as json
connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = connection.channel()
channel.queue_declare(queue='raw_post', durable=True)
for i in range(5000):
info = {"info": "test", "value": i}
channel.basic_publish(exchange='',
routing_key='raw_post',
body=json.dumps(info),
properties=pika.BasicProperties(
delivery_mode=2, # make message persistent
))
print(" [x] Sent 'Hello World!' {}".format(i))
connection.close()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.