一、交换器
rabbitmq有四种交换器,分别如下:
1、direct:如果路由键完全匹配的话,消息才会被投放到相应的队列。
2、fanout:当发送一条消息到fanout交换器上时,它会把消息投放到所有附加在此交换器上的队列。
3、topic:设置模糊的绑定方式,“*”操作符将“.”视为分隔符,匹配单个字符;“#”操作符没有分块的概念,它将任意“.”均视为关键字的匹配部分,能够匹配多个字符。
4、header:根据发送的消息内容中的headers属性进行匹配
二、队列
1、简单队列:一个消费者一个生产者
生产者
# !/usr/bin/env python
# -*- coding: utf-8 -*-
import pika
host = "10.31.4.96"
port = 5672
user = "root"
passwd = "12345678"
virtual_host = "/"
credentials = pika.PlainCredentials(user,passwd) # 认证凭证
connection = pika.BlockingConnection(pika.ConnectionParameters(host=host,port=port,virtual_host=virtual_host,credentials=credentials)) # 建立连接
channel = connection.channel(channel_number=2) # 创建信道
channel.queue_declare(queue='hello') # 创建队列
channel.basic_publish(exchange='',routing_key='hello',body='Hello World!') # 使用默认的交换器,exchange设置为空,routing_key设置队列名称
print(" [x] Sent 'Hello World!'")
connection.close()
消费者
# !/usr/bin/env python
# -*- coding: utf-8 -*-
import pika, sys, os
host = "10.31.4.96"
port = 5672
user = "root"
passwd = "12345678"
virtual_host = "/"
def main():
credentials = pika.PlainCredentials(user, passwd) # 认证凭证
connection = pika.BlockingConnection(pika.ConnectionParameters(host=host, port=port, virtual_host=virtual_host, credentials=credentials)) # 建立连接
channel = connection.channel(channel_number=2) # 创建信道
channel.queue_declare(queue='hello') # 创建队列
def callback(ch, method, properties, body):
print(" [x] Received %r" % body)
channel.basic_consume(queue='hello', on_message_callback=callback, auto_ack=True)
print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
print('Interrupted')
try:
sys.exit(0)
except SystemExit:
os._exit(0)
2、work模式:一个生产者对应多个消费者,但是只能有一个消费者获得消息
# !/usr/bin/env python
# -*- coding: utf-8 -*-
import pika,sys
host = "10.31.4.96"
port = 5672
user = "root"
passwd = "12345678"
virtual_host = "/"
credentials = pika.PlainCredentials(user,passwd) # 认证凭证
connection = pika.BlockingConnection(pika.ConnectionParameters(host=host,port=port,virtual_host=virtual_host,credentials=credentials)) # 建立连接
channel = connection.channel() # 创建信道
channel.queue_declare(queue='hello',durable=True) # 创建队列,durable=True持久化队列
message = ' '.join(sys.argv[1:]) or "Hello World!"
channel.basic_publish(exchange='',
routing_key='hello',
body=message,
properties=pika.BasicProperties(
delivery_mode = 2, # 消息持久化
)
)
print(" [x] Sent %r" % message)
消费者
# !/usr/bin/env python
# -*- coding: utf-8 -*-
import pika, sys, os,time
host = "10.31.4.96"
port = 5672
user = "root"
passwd = "12345678"
virtual_host = "/"
def main():
credentials = pika.PlainCredentials(user, passwd) # 认证凭证
connection = pika.BlockingConnection(pika.ConnectionParameters(host=host, port=port, virtual_host=virtual_host, credentials=credentials)) # 建立连接
channel = connection.channel() # 创建信道
channel.queue_declare(queue='hello',durable=True) # 创建队列,durable=True持久化队列
def callback(ch, method, properties, body):
print(" [x] Received %r" % body.decode()) # 接收到消息
time.sleep(body.count(b'.')) # 处理业务逻辑
print(" [x] Done %r" % body.decode())
ch.basic_ack(delivery_tag=method.delivery_tag) # 手动回复ack
channel.basic_qos(prefetch_count=4)
channel.basic_consume(queue='hello', on_message_callback=callback, auto_ack=False) # auto_ack=False自动回复关闭后,需要手动回复ack
print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
print('Interrupted')
try:
sys.exit(0)
except SystemExit:
os._exit(0)
3、发布订阅模式:一个消费者将消息首先发送到交换器,交换器绑定到多个队列,然后被监听该队列的消费者所接收并消费
生产者
# !/usr/bin/env python
# -*- coding: utf-8 -*-
import pika,sys
host = "10.31.4.96"
port = 5672
user = "root"
passwd = "12345678"
virtual_host = "/"
credentials = pika.PlainCredentials(user,passwd) # 认证凭证
connection = pika.BlockingConnection(pika.ConnectionParameters(host=host,port=port,virtual_host=virtual_host,credentials=credentials)) # 建立连接
channel = connection.channel() # 创建信道
channel.exchange_declare(exchange='logs',exchange_type='fanout') # 定义交换器
message = ' '.join(sys.argv[1:]) or "info: Hello World!"
channel.basic_publish(exchange='logs', routing_key='', body=message)
print(" [x] Sent %r" % message)
connection.close()
消费者
# !/usr/bin/env python
# -*- coding: utf-8 -*-
import pika, sys, os,time
host = "10.31.4.96"
port = 5672
user = "root"
passwd = "12345678"
virtual_host = "/"
credentials = pika.PlainCredentials(user, passwd) # 认证凭证
connection = pika.BlockingConnection(pika.ConnectionParameters(host=host, port=port, virtual_host=virtual_host, credentials=credentials)) # 建立连接
channel = connection.channel() # 创建信道
channel.exchange_declare(exchange='logs', exchange_type='fanout')
result = channel.queue_declare(queue='', exclusive=True) # queue='' 随机队列名称,exclusive=True:临时队列
queue_name = result.method.queue
channel.queue_bind(exchange='logs', queue=queue_name)
print(' [*] Waiting for logs. To exit press CTRL+C')
def callback(ch, method, properties, body):
print(" [x] %r" % body)
channel.basic_consume(queue=queue_name, on_message_callback=callback, auto_ack=True)
channel.start_consuming()
4、路由模式
生产者将消息发送到direct交换器,在绑定队列和交换器的时候有一个路由key,生产者发送的消息会指定一个路由key,那么消息只会发送到相应key相同的队列,接着监听该队列的消费者消费消息。也就是让消费者有选择性的接收消息。
生产者
# !/usr/bin/env python
# -*- coding: utf-8 -*-
import pika,sys
host = "10.31.4.96"
port = 5672
user = "root"
passwd = "12345678"
virtual_host = "/"
credentials = pika.PlainCredentials(user,passwd) # 认证凭证
connection = pika.BlockingConnection(pika.ConnectionParameters(host=host,port=port,virtual_host=virtual_host,credentials=credentials)) # 建立连接
channel = connection.channel() # 创建信道
channel.exchange_declare(exchange='direct_logs', exchange_type='direct')
severity = sys.argv[1] if len(sys.argv) > 1 else 'info'
message = ' '.join(sys.argv[2:]) or 'Hello World!'
channel.basic_publish(exchange='direct_logs', routing_key=severity, body=message)
print(" [x] Sent %r:%r" % (severity, message))
connection.close()
消费者
# !/usr/bin/env python
# -*- coding: utf-8 -*-
import pika, sys, os,time
host = "10.31.4.96"
port = 5672
user = "root"
passwd = "12345678"
virtual_host = "/"
credentials = pika.PlainCredentials(user, passwd) # 认证凭证
connection = pika.BlockingConnection(pika.ConnectionParameters(host=host, port=port, virtual_host=virtual_host, credentials=credentials)) # 建立连接
channel = connection.channel() # 创建信道
channel.exchange_declare(exchange='direct_logs', exchange_type='direct')
result = channel.queue_declare(queue='', exclusive=True)# queue='' 随机队列名称,exclusive=True:临时队列
queue_name = result.method.queue
severities = sys.argv[1:]
if not severities:
sys.stderr.write("Usage: %s [info] [warning] [error]\n" % sys.argv[0])
sys.exit(1)
for severity in severities:
channel.queue_bind(exchange='direct_logs', queue=queue_name, routing_key=severity)
print(' [*] Waiting for logs. To exit press CTRL+C')
def callback(ch, method, properties, body):
print(" [x] %r:%r" % (method.routing_key, body))
channel.basic_consume(queue=queue_name, on_message_callback=callback, auto_ack=True)
channel.start_consuming()
python2.7 send.py error "Run. Run. Or it will explode."
python2.7 receive.py info warning error
python2.7 receive.py info
5、主题模式
通配符模式通俗的来讲就是模糊匹配。符号“#”表示匹配一个或多个词,符号“*”表示匹配一个词。
生产者
# !/usr/bin/env python
# -*- coding: utf-8 -*-
import pika, sys, os,time
host = "10.31.4.96"
port = 5672
user = "root"
passwd = "12345678"
virtual_host = "/"
credentials = pika.PlainCredentials(user, passwd) # 认证凭证
connection = pika.BlockingConnection(pika.ConnectionParameters(host=host, port=port, virtual_host=virtual_host, credentials=credentials)) # 建立连接
channel = connection.channel() # 创建信道
channel.exchange_declare(exchange='topic_logs', exchange_type='topic')
result = channel.queue_declare('', exclusive=True)
queue_name = result.method.queue
binding_keys = sys.argv[1:]
if not binding_keys:
sys.stderr.write("Usage: %s [binding_key]...\n" % sys.argv[0])
sys.exit(1)
for binding_key in binding_keys:
channel.queue_bind(
exchange='topic_logs', queue=queue_name, routing_key=binding_key)
print(' [*] Waiting for logs. To exit press CTRL+C')
def callback(ch, method, properties, body):
print(" [x] %r:%r" % (method.routing_key, body))
channel.basic_consume(
queue=queue_name, on_message_callback=callback, auto_ack=True)
channel.start_consuming()
消费者
# !/usr/bin/env python
# -*- coding: utf-8 -*-
import pika,sys
host = "10.31.4.96"
port = 5672
user = "root"
passwd = "12345678"
virtual_host = "/"
credentials = pika.PlainCredentials(user,passwd) # 认证凭证
connection = pika.BlockingConnection(pika.ConnectionParameters(host=host,port=port,virtual_host=virtual_host,credentials=credentials)) # 建立连接
channel = connection.channel() # 创建信道
channel.exchange_declare(exchange='topic_logs', exchange_type='topic')
routing_key = sys.argv[1] if len(sys.argv) > 2 else 'anonymous.info'
message = ' '.join(sys.argv[2:]) or 'Hello World!'
channel.basic_publish(
exchange='topic_logs', routing_key=routing_key, body=message)
print(" [x] Sent %r:%r" % (routing_key, message))
connection.close()
python2.7 send.py "kern.critical" "A critical kernel error"
python2.7 receive.py "kern.*" "*.critical"
python2.7 receive.py "*.critical"