RabbitMQ-Python
详细文档请参考:https://www.aliyundrive.com/s/VgzyVVCUxSv
RabbitMQ原理图示:
一:RabbitMQ消息类型-HelloWorld
1 #__author__:Kelvin 2 #date:2020/4/14 15:10 3 import pika 4 5 credentials = pika.PlainCredentials('kelvin', '123456') 6 connection = pika.BlockingConnection(pika.ConnectionParameters('localhost', 5672, "vhost01",credentials)) 7 #创建通道,通过通道和队列进行信息发送与获取 8 channel = connection.channel() 9 # 声明queue 10 channel.queue_declare(queue='q1') 11 channel.basic_publish(exchange='',routing_key='q1',body='Hello World!') 12 print("消息已经成功发送...") 13 connection.close()
1 # __author__:Kelvin 2 # date:2020/4/14 15:12 3 import pika 4 5 credentials = pika.PlainCredentials('kelvin', '123456') 6 connection = pika.BlockingConnection(pika.ConnectionParameters('localhost', 5672, "vhost01", credentials)) 7 channel = connection.channel() 8 9 channel.queue_declare(queue='q1') 10 def callback(ch, method, properties, body): 11 print("接收的消息:%r" % body) 12 channel.basic_consume('q1', callback, True) 13 channel.start_consuming()
二:RabbitMQ消息类型-Work
如果Rabbit只管按顺序把消息发到各个消费者身上,不考虑消费者负载的话,很可能出现,一个机器配置不高的消费者那里堆积了很多消息处理不完,同时配置高的消费者却一直很轻松。为解决此问题,可以在各个消费者端,配置channel.basic_qos(prefetch_count
=
1
)(现在最新版这样使用会报错,应该为
,意思就是告诉RabbitMQ在我这个消费者当前消息还没处理完的时候就不要再给我发新消息了。channel.basic_qos(0,
1
)
)
1:普通均分消息
原理图示:
1 # __author__:Kelvin 2 # date:2020/4/14 21:00 3 import pika 4 import time 5 import sys 6 7 credentials = pika.PlainCredentials('kelvin', '123456') 8 connection = pika.BlockingConnection(pika.ConnectionParameters('localhost', 5672, "vhost01", credentials)) 9 channel = connection.channel() 10 # 声明queue 11 channel.queue_declare(queue='q2') 12 for i in range(20): 13 message = "Hello World! %s" % i 14 channel.basic_publish(exchange='',routing_key='q2', 15 body=message, 16 ) 17 print(" [x] Sent %r" % message) 18 connection.close()
1 # __author__:Kelvin 2 # date:2020/4/14 21:03 3 import pika, time 4 5 credentials = pika.PlainCredentials('kelvin', '123456') 6 connection = pika.BlockingConnection(pika.ConnectionParameters('localhost', 5672, "vhost01", credentials)) 7 channel = connection.channel() 8 9 # 声明queue 10 channel.queue_declare(queue='q2') 11 12 def callback(ch, method, properties, body): 13 print(" [x] Received %r" % body) 14 time.sleep(0.2) 15 print("method.delivery_tag", method.delivery_tag) 16 ch.basic_ack(delivery_tag=method.delivery_tag) 17 18 19 channel.basic_consume("q2",callback,False) 20 channel.start_consuming()
2:队列、消息持久化均分消息
原理图示:
1 # __author__:Kelvin 2 # date:2020/4/14 21:00 3 import pika 4 import time 5 import sys 6 7 credentials = pika.PlainCredentials('kelvin', '123456') 8 connection = pika.BlockingConnection(pika.ConnectionParameters('localhost', 5672, "vhost01", credentials)) 9 channel = connection.channel() 10 # 声明queue 11 channel.queue_declare(queue='q2') 12 message = "Hello World!" 13 channel.basic_publish(exchange='', routing_key='q2', 14 body=message, 15 properties=pika.BasicProperties( 16 delivery_mode=2, 17 )) #消息持久化 ***** 18 print(" [x] Sent %r" % message) 19 connection.close()
1 # __author__:Kelvin 2 # date:2020/4/14 21:03 3 import pika, time 4 5 credentials = pika.PlainCredentials('kelvin', '123456') 6 connection = pika.BlockingConnection(pika.ConnectionParameters('localhost', 5672, "vhost01", credentials)) 7 channel = connection.channel() 8 9 # 声明queue 10 channel.queue_declare(queue='q2',durable=True) #*****队列持久化 11 12 def callback(ch, method, properties, body): 13 print(" [x] Received %r" % body) 14 time.sleep(0.2) 15 print("method.delivery_tag", method.delivery_tag) 16 ch.basic_ack(delivery_tag=method.delivery_tag) 17 18 19 channel.basic_consume("q2",callback,False) 20 channel.start_consuming()
3:根据接收者能力大小接收消息(不均分消息)
原理图示:
同时设置channel.basic_qos(0,1),目的是为了让RabbitMQ服务器发送数据时,如果当前消费者当前消息还没有处理完就不要再发送消息了,channel.basic_consume("q2",callback,False)中的no_ack=False,目的是为了不让RabbitMQ主动确认接收消息,同时在callback回调函数最后主动向RabbitMQ服务器确认接收消息(也就是在接收消息完毕后接收端主动提交确认),
1 # __author__:Kelvin 2 # date:2020/4/14 21:00 3 import pika 4 import time 5 import sys 6 7 credentials = pika.PlainCredentials('kelvin', '123456') 8 connection = pika.BlockingConnection(pika.ConnectionParameters('localhost', 5672, "vhost01", credentials)) 9 channel = connection.channel() 10 # 声明queue 11 channel.queue_declare(queue='q2') 12 for i in range(20): 13 message = "Hello World! %s" % i 14 channel.basic_publish(exchange='',routing_key='q2', 15 body=message, 16 ) 17 print(" [x] Sent %r" % message) 18 connection.close()
1 # __author__:Kelvin 2 # date:2020/4/14 21:03 3 import pika, time 4 5 credentials = pika.PlainCredentials('kelvin', '123456') 6 connection = pika.BlockingConnection(pika.ConnectionParameters('localhost', 5672, "vhost01", credentials)) 7 channel = connection.channel() 8 channel.basic_qos(0,1) 9 # 声明queue 10 channel.queue_declare(queue='q2') 11 12 def callback(ch, method, properties, body): 13 print(" [x] Received %r" % body) 14 time.sleep(0.2) 15 print("method.delivery_tag", method.delivery_tag) 16 ch.basic_ack(delivery_tag=method.delivery_tag) 17 18 19 channel.basic_consume("q2",callback,False) 20 channel.start_consuming()
1 # __author__:Kelvin 2 # date:2020/4/14 21:03 3 import pika, time 4 5 credentials = pika.PlainCredentials('kelvin', '123456') 6 connection = pika.BlockingConnection(pika.ConnectionParameters('localhost', 5672, "vhost01", credentials)) 7 channel = connection.channel() 8 channel.basic_qos(0,1) 9 # 声明queue 10 channel.queue_declare(queue='q2') 11 12 13 def callback(ch, method, properties, body): 14 print(" [x] Received %r" % body) 15 time.sleep(1) 16 print("method.delivery_tag", method.delivery_tag) 17 ch.basic_ack(delivery_tag=method.delivery_tag) #***** 18 19 20 channel.basic_consume("q2",callback,False) #*****False 21 channel.start_consuming()
三:RabbitMQ消息类型-fanout(广播)
原理图示:
1 # __author__:Kelvin 2 # date:2020/4/14 21:00 3 import pika 4 import time 5 import sys 6 7 credentials = pika.PlainCredentials('kelvin', '123456') 8 connection = pika.BlockingConnection(pika.ConnectionParameters('localhost', 5672, "vhost01", credentials)) 9 channel = connection.channel() 10 #使用交换机 11 channel.exchange_declare(exchange='logs',exchange_type='fanout') #***** 12 message =" Hello World!" 13 #定义交换机名称 14 channel.basic_publish(exchange='logs',routing_key='',body=message) #***** 15 print("成功发送消息: %r" % message) 16 connection.close()
1 # __author__:Kelvin 2 # date:2020/4/14 21:03 3 import pika, time 4 5 credentials = pika.PlainCredentials('kelvin', '123456') 6 connection = pika.BlockingConnection(pika.ConnectionParameters('localhost', 5672, "vhost01", credentials)) 7 channel = connection.channel() 8 channel.exchange_declare(exchange='logs',exchange_type='fanout')#使用交换机 类型为广播***** 9 result = channel.queue_declare("",exclusive=True) # 不指定queue名字,rabbit会随机分配一个名字,exclusive=True会在使用此queue的消费者断开后,自动将queue删除 10 queue_name = result.method.queue 11 channel.queue_bind(exchange='logs',queue=queue_name) #通道绑定随机分配的队列名***** 12 13 def callback(ch, method, properties, body): 14 print("接收到消息:%r" % body) 15 channel.basic_consume(queue_name,callback,True) 16 channel.start_consuming()
1 # __author__:Kelvin 2 # date:2020/4/14 21:03 3 import pika, time 4 5 credentials = pika.PlainCredentials('kelvin', '123456') 6 connection = pika.BlockingConnection(pika.ConnectionParameters('localhost', 5672, "vhost01", credentials)) 7 channel = connection.channel() 8 channel.exchange_declare(exchange='logs',exchange_type='fanout')#使用交换机 类型为广播***** 9 result = channel.queue_declare("",exclusive=True) # 不指定queue名字,rabbit会随机分配一个名字,exclusive=True会在使用此queue的消费者断开后,自动将queue删除 10 queue_name = result.method.queue 11 channel.queue_bind(exchange='logs',queue=queue_name) #通道绑定随机分配的队列名***** 12 13 def callback(ch, method, properties, body): 14 print("接收到消息:%r" % body) 15 channel.basic_consume(queue_name,callback,True) 16 channel.start_consuming()
1 # __author__:Kelvin 2 # date:2020/4/14 21:03 3 import pika, time 4 5 credentials = pika.PlainCredentials('kelvin', '123456') 6 connection = pika.BlockingConnection(pika.ConnectionParameters('localhost', 5672, "vhost01", credentials)) 7 channel = connection.channel() 8 channel.exchange_declare(exchange='logs',exchange_type='fanout')#使用交换机 类型为广播***** 9 result = channel.queue_declare("",exclusive=True) # 不指定queue名字,rabbit会随机分配一个名字,exclusive=True会在使用此queue的消费者断开后,自动将queue删除 10 queue_name = result.method.queue 11 channel.queue_bind(exchange='logs',queue=queue_name) #通道绑定随机分配的队列名***** 12 13 def callback(ch, method, properties, body): 14 print("接收到消息:%r" % body) 15 channel.basic_consume(queue_name,callback,True) 16 channel.start_consuming()
四:RabbitMQ消息类型-direct(组播)
原理图示:
RabbitMQ还支持根据关键字发送,即:队列绑定关键字,发送者将数据根据关键字发送到消息exchange的routing_key属性,exchange根据 关键字 判定应该将数据发送至指定队列。
1 # __author__:Kelvin 2 # date:2020/4/14 21:00 3 import pika 4 import time 5 import sys 6 7 credentials = pika.PlainCredentials('kelvin', '123456') 8 connection = pika.BlockingConnection(pika.ConnectionParameters('localhost', 5672, "vhost01", credentials)) 9 channel = connection.channel() 10 #使用交换机 11 channel.exchange_declare(exchange='direct_logs',exchange_type='direct') 12 message =" Hello World!" 13 severity="info" 14 channel.basic_publish(exchange='direct_logs', 15 routing_key=severity, 16 body=message) 17 print("成功发送消息: %r:%r" % (severity, message)) 18 connection.close()
1 # __author__:Kelvin 2 # date:2020/4/14 21:03 3 import pika, time 4 5 credentials = pika.PlainCredentials('kelvin', '123456') 6 connection = pika.BlockingConnection(pika.ConnectionParameters('localhost', 5672, "vhost01", credentials)) 7 channel = connection.channel() 8 channel.exchange_declare(exchange='direct_logs',exchange_type='direct') 9 result = channel.queue_declare("",exclusive=True) 10 queue_name = result.method.queue 11 severities=["error","warning"] 12 for severity in severities: 13 channel.queue_bind(exchange='direct_logs',queue=queue_name,routing_key=severity) 14 def callback(ch, method, properties, body): 15 print("接收到消息:%r:%r" % (method.routing_key, body)) 16 channel.basic_consume(queue_name,callback,True) 17 channel.start_consuming()
1 # __author__:Kelvin 2 # date:2020/4/14 21:03 3 import pika, time 4 5 credentials = pika.PlainCredentials('kelvin', '123456') 6 connection = pika.BlockingConnection(pika.ConnectionParameters('localhost', 5672, "vhost01", credentials)) 7 channel = connection.channel() 8 channel.exchange_declare(exchange='direct_logs',exchange_type='direct') 9 result = channel.queue_declare("",exclusive=True) 10 queue_name = result.method.queue 11 severities=["warning"] 12 for severity in severities: 13 channel.queue_bind(exchange='direct_logs',queue=queue_name,routing_key=severity) 14 def callback(ch, method, properties, body): 15 print("接收到消息:%r:%r" % (method.routing_key, body)) 16 channel.basic_consume(queue_name,callback,True) 17 channel.start_consuming()
1 # __author__:Kelvin 2 # date:2020/4/14 21:03 3 import pika, time 4 5 credentials = pika.PlainCredentials('kelvin', '123456') 6 connection = pika.BlockingConnection(pika.ConnectionParameters('localhost', 5672, "vhost01", credentials)) 7 channel = connection.channel() 8 channel.exchange_declare(exchange='direct_logs',exchange_type='direct') 9 result = channel.queue_declare("",exclusive=True) 10 queue_name = result.method.queue 11 severities=["error","warning","info"] 12 for severity in severities: 13 channel.queue_bind(exchange='direct_logs',queue=queue_name,routing_key=severity) 14 def callback(ch, method, properties, body): 15 print("接收到消息:%r:%r" % (method.routing_key, body)) 16 channel.basic_consume(queue_name,callback,True) 17 channel.start_consuming()
五:RabbitMQ消息类型-topic(更细致的过滤-组播)
原理图示:
1 # __author__:Kelvin 2 # date:2020/4/14 21:00 3 import pika 4 import time 5 import sys 6 7 credentials = pika.PlainCredentials('kelvin', '123456') 8 connection = pika.BlockingConnection(pika.ConnectionParameters('localhost', 5672, "vhost01", credentials)) 9 channel = connection.channel() 10 #使用交换机 11 channel.exchange_declare(exchange='topic_logs',exchange_type='topic') 12 message =" Hello World!" 13 severity="error.first" 14 channel.basic_publish(exchange='topic_logs', 15 routing_key=severity, 16 body=message) 17 print("成功发送消息: %r:%r" % (severity, message)) 18 connection.close()
1 # __author__:Kelvin 2 # date:2020/4/14 21:03 3 import pika, time 4 5 credentials = pika.PlainCredentials('kelvin', '123456') 6 connection = pika.BlockingConnection(pika.ConnectionParameters('localhost', 5672, "vhost01", credentials)) 7 channel = connection.channel() 8 channel.exchange_declare(exchange='topic_logs',exchange_type='topic') 9 result = channel.queue_declare("",exclusive=True) 10 queue_name = result.method.queue 11 severity="info.*" 12 channel.queue_bind(exchange='topic_logs',queue=queue_name,routing_key=severity) 13 def callback(ch, method, properties, body): 14 print("接收到消息:%r:%r" % (method.routing_key, body)) 15 channel.basic_consume(queue_name,callback,True) 16 channel.start_consuming()
1 # __author__:Kelvin 2 # date:2020/4/14 21:03 3 import pika, time 4 5 credentials = pika.PlainCredentials('kelvin', '123456') 6 connection = pika.BlockingConnection(pika.ConnectionParameters('localhost', 5672, "vhost01", credentials)) 7 channel = connection.channel() 8 channel.exchange_declare(exchange='topic_logs',exchange_type='topic') 9 result = channel.queue_declare("",exclusive=True) 10 queue_name = result.method.queue 11 severity="info.student.*" 12 channel.queue_bind(exchange='topic_logs',queue=queue_name,routing_key=severity) 13 def callback(ch, method, properties, body): 14 print("接收到消息:%r:%r" % (method.routing_key, body)) 15 channel.basic_consume(queue_name,callback,True) 16 channel.start_consuming()
1 # __author__:Kelvin 2 # date:2020/4/14 21:03 3 import pika, time 4 5 credentials = pika.PlainCredentials('kelvin', '123456') 6 connection = pika.BlockingConnection(pika.ConnectionParameters('localhost', 5672, "vhost01", credentials)) 7 channel = connection.channel() 8 channel.exchange_declare(exchange='topic_logs',exchange_type='topic') 9 result = channel.queue_declare("",exclusive=True) 10 queue_name = result.method.queue 11 severity="#" 12 channel.queue_bind(exchange='topic_logs',queue=queue_name,routing_key=severity) 13 def callback(ch, method, properties, body): 14 print("接收到消息:%r:%r" % (method.routing_key, body)) 15 channel.basic_consume(queue_name,callback,True) 16 channel.start_consuming()
六:RabbitMQ消息类型-RPC
原理图示:
1 #__author__:Kelvin 2 #date:2020/4/15 0:20 3 import pika 4 import uuid 5 6 7 class FibonacciRpcClient(object): 8 def __init__(self): 9 self.credentials = pika.PlainCredentials('kelvin', '123456') 10 self.connection = pika.BlockingConnection(pika.ConnectionParameters('localhost', 5672, "vhost01", self.credentials)) 11 self.channel = self.connection.channel() 12 result = self.channel.queue_declare("",exclusive=True) 13 self.callback_queue = result.method.queue 14 self.channel.basic_consume(self.callback_queue,self.on_response,True) 15 16 def on_response(self, ch, method, props, body): 17 if self.corr_id == props.correlation_id: 18 self.response = body 19 20 def call(self, n): 21 self.response = None 22 self.corr_id = str(uuid.uuid4()) 23 self.channel.basic_publish(exchange='', 24 routing_key='rpc_queue', 25 properties=pika.BasicProperties( 26 reply_to=self.callback_queue, 27 correlation_id=self.corr_id, 28 ), 29 body=str(n)) 30 while self.response is None: 31 self.connection.process_data_events() 32 return int(self.response) 33 34 fibonacci_rpc = FibonacciRpcClient() 35 print("请求计算 fib(10)") 36 response = fibonacci_rpc.call(10) 37 print("获取返回结果 %r" % response)
1 # __author__:Kelvin 2 # date:2020/4/15 0:21 3 import pika 4 import time 5 6 credentials = pika.PlainCredentials('kelvin', '123456') 7 connection = pika.BlockingConnection(pika.ConnectionParameters('localhost', 5672, "vhost01", credentials)) 8 channel = connection.channel() 9 channel.queue_declare(queue='rpc_queue') 10 11 def fib(n): 12 if n == 0: 13 return 0 14 elif n == 1: 15 return 1 16 else: 17 return fib(n - 1) + fib(n - 2) 18 19 20 def on_request(ch, method, props, body): 21 n = int(body) 22 print("客户端请求计算的参数为:%s"%n) 23 response = fib(n) 24 ch.basic_publish(exchange='', 25 routing_key=props.reply_to, 26 properties=pika.BasicProperties(correlation_id=props.correlation_id), 27 body=str(response)) 28 ch.basic_ack(delivery_tag=method.delivery_tag) 29 30 channel.basic_qos(prefetch_count=1) 31 channel.basic_consume('rpc_queue',on_request) 32 channel.start_consuming()
RabbitMQ运行环境erlang和rabbitmq服务器软件下载地址:
链接:https://pan.baidu.com/s/12WEKqztnHDZE0_xfkSn7fg
提取码:zasx