基本用法流程

  • 生产者:
  • 建立socket连接上rabbitmq
1 connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
1 pika.ConnectionParameters(host=_DEFAULT, port=_DEFAULT, virtual_host=_DEFAULT, credentials=_DEFAULT, channel_max=_DEFAULT, frame_max=_DEFAULT, heartbeat=_DEFAULT, ssl=_DEFAULT, ssl_options=_DEFAULT, connection_attempts=_DEFAULT, retry_delay=_DEFAULT, socket_timeout=_DEFAULT, locale=_DEFAULT, backpressure_detection=_DEFAULT, blocked_connection_timeout=_DEFAULT, client_properties=_DEFAULT, tcp_options=_DEFAULT, **kwargs)
  • 常用参数
    • host,与rabbitmq服务器连接,设置为localhost表示与本机的rabbitmq建立连接,通常程序与rabbitmq服务需要在统一环境方可使用
  • port,默认5672
  • credentials:用户认证,使用如pika.credentials.PlainCredentials进行认证
  • 建立通信通道
channel = connection.channel()
  • 建立队列/建立交换机
  • 简单模式建立队列
result = channel.queue_declare(self, queue='', passive=False, durable=False, exclusive=False, auto_delete=False, arguments=None)
  • 常用参数
    • queue,队列名
    • durable,消息是放在队列由消费者取走,该参数表示取走时是否备份一份
    • exclusive,队列是否本连接独占
  • 建立的队列
    • queue = result.method.queue
  • 其他模式建立交换机
channel.exchange_declare(exchange=None, exchange_type='direct', passive=False, durable=False, auto_delete=False, internal=False, arguments=None)
  • 常用参数
    • exchange,交换机名称
    • exchange_type,重点,交换机的模式,有三种:fanout,direct,topic
    • durable,该参数表示消费者取走时是否备份一份
  • 传输数据
channel.basic_publish(exchange, routing_key, body, properties=None, mandatory=False, immediate=False)
  • 常用参数
    • exchange,传输到交换机的名,可为’‘,表示不传输到交换机
    • routing_key,传输到队列的名,可为’‘,表示不传输到队列
    • body,传输的数据properties,额外参数,必须是pika.BasicProperties的实例

    • pika.BasicProperties(content_type=None, content_encoding=None, headers=None, delivery_mode=None, priority=None, correlation_id=None, reply_to=None, expiration=None, message_id=None, timestamp=None, type=None, user_id=None, app_id=None, cluster_id=None)


    • delivery_mode,传输模式
        • 设置为2,表示对消息进行持久化
      • reply_to,传递队列,可用于RPC回调队列
      • correlation_id,关联ID,可用于RPC回调时识别身份
  • 结束
  • connection.close()
  • 消费者
  • 建立socket连接上rabbitmq
  • 同上生产者
  • 建立通信通道
  • channel = connection.channel()
  • 建立交换机[可选]
  • 同上生产者
  • 建立队列
  • 同上生产者
  • 定制消息处理规则
  • 定义回调函数
def callback(ch, method, properties, body): pass
  • 定制规则
  • channel.basic_consume(consumer_callback, queue, no_ack=False, exclusive=False, consumer_tag=None, arguments=None)
  • consumer_callback,回调函数
  • queue,接收消息队列
  • no_ack,是否不应答,True表示不应答,False表示应答
  • 是否给rabbitmq返回,已收到并处理消息
  • 阻塞监听队列,当有消息,则按照规则处理
  • channel.start_consuming()

RabbitMQ工作模型

  • 工作模型指的是生产者和消费者之间使用不同规则通信使用的RabbitMQ的模式

简单模式

python rabbitmq接收消息 python连接rabbitmq_RPC

  • 示例
  • 生产者
1 import pika
 2         
 3   # 封装socket通信,建立连接
 4   connection = pika.BlockingConnection(
 5       pika.ConnectionParameters(
 6           host='192.168.40.128',
 7           port=5672,
 8           credentials=pika.credentials.PlainCredentials(
 9               username='admin',
10               password='123456'
11           )
12       ))
13         
14   # 创建通道对象
15   channel = connection.channel()
16         
17   # 创建一个队列,名字为hello
18   channel.queue_declare(queue='hello')
19         
20   # 直接向队列推送消息
21   msg = "兔子"
22   num = 10
23   for i in range(num):
24       channel.basic_publish(
25           exchange='',                # 值为空表示简单模式
26           routing_key='hello',        # 队列名
27           body=''.join([msg, str(i)])    # 发送数据
28       )
29         
30   print("Sent '%s' * %s" % (msg, num))
31   connection.close()
  • 消费者
1 import pika
 2         
 3   # 封装socket通信,建立连接
 4   connection = pika.BlockingConnection(
 5       pika.ConnectionParameters(
 6           host='192.168.40.128',
 7           port=5672,
 8           credentials=pika.credentials.PlainCredentials(
 9               username='admin',
10               password='123456'
11           )
12       ))
13         
14   # 创建通道对象
15   channel = connection.channel()
16         
17   # 创建一个叫hello的队列,有则连接该队列
18   channel.queue_declare(queue='hello')
19         
20   # 定义回调函数
21   def callback(ch, method, properties, body):
22       print(" [x] Received %r" % body.decode("utf-8"))
23         
24   # 设置执行命令
25   channel.basic_consume(
26       callback,
27       queue='hello',
28       no_ack=True
29   )
30         
31   print(' [*] Waiting for messages. To exit press CTRL+C')
32   # 执行命令
33   channel.start_consuming()

exchange模式(三种)

fanout
  • 分发模式,报纸订阅模式,生产者生产一份数据,交换机为每个消费者绑定的队列发送一样的数据

python rabbitmq接收消息 python连接rabbitmq_python rabbitmq接收消息_02

  • 生产者
1 import pika
 2   import sys
 3     
 4   connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
 5   channel = connection.channel()
 6     
 7   channel.exchange_declare(exchange='logs',
 8                            exchange_type='fanout')
 9     
10   message = ' '.join(sys.argv[1:]) or "info: Hello World!"
11   channel.basic_publish(exchange='logs',
12                         routing_key='',
13                         body=message)
14   print(" [x] Sent %r" % message)
15   connection.close()
  • 消费者
1   import pika
 2     
 3   connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
 4   channel = connection.channel()
 5     
 6   channel.exchange_declare(exchange='logs',
 7                            exchange_type='fanout')
 8     
 9   result = channel.queue_declare(exclusive=True)
10   queue_name = result.method.queue
11     
12   channel.queue_bind(exchange='logs',
13                      queue=queue_name)
14     
15   print(' [*] Waiting for logs. To exit press CTRL+C')
16     
17   def callback(ch, method, properties, body):
18       print(" [x] %r" % body)
19     
20   channel.basic_consume(callback,
21                         queue=queue_name,
22                         no_ack=True)
23     
24   channel.start_consuming()
direct
  • 关键字指定发送,

python rabbitmq接收消息 python连接rabbitmq_RPC_03

  • 生产者
1 import pika
 2   import sys
 3     
 4   connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
 5   channel = connection.channel()
 6     
 7   channel.exchange_declare(exchange='direct_logs',
 8                            exchange_type='direct')
 9     
10   severity = sys.argv[1] if len(sys.argv) > 2 else 'info'
11   message = ' '.join(sys.argv[2:]) or 'Hello World!'
12   channel.basic_publish(exchange='direct_logs',
13                         routing_key=severity,
14                         body=message)
15   print(" [x] Sent %r:%r" % (severity, message))
16   connection.close()
  • 消费者
1 import pika
 2   import sys
 3     
 4   connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
 5   channel = connection.channel()
 6     
 7   channel.exchange_declare(exchange='direct_logs',
 8                            exchange_type='direct')
 9     
10   result = channel.queue_declare(exclusive=True)
11   queue_name = result.method.queue
12     
13   severities = sys.argv[1:]
14   if not severities:
15       sys.stderr.write("Usage: %s [info] [warning] [error]\n" % sys.argv[0])
16       sys.exit(1)
17     
18   for severity in severities:
19       channel.queue_bind(exchange='direct_logs',
20                          queue=queue_name,
21                          routing_key=severity)
22     
23   print(' [*] Waiting for logs. To exit press CTRL+C')
24     
25   def callback(ch, method, properties, body):
26       print(" [x] %r:%r" % (method.routing_key, body))
27     
28   channel.basic_consume(callback,
29                         queue=queue_name,
30                         no_ack=True)
31     
32   channel.start_consuming()
  • 测试
  • python producer.py warning error > logs_from_rabbit.log
  • python comsumer.py info warning error
topic

python rabbitmq接收消息 python连接rabbitmq_python_04

  • 生产者
1 import pika
 2   import sys
 3     
 4   connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
 5   channel = connection.channel()
 6     
 7   channel.exchange_declare(exchange='topic_logs',
 8                            exchange_type='topic')
 9     
10   routing_key = sys.argv[1] if len(sys.argv) > 2 else 'anonymous.info'
11   message = ' '.join(sys.argv[2:]) or 'Hello World!'
12   channel.basic_publish(exchange='topic_logs',
13                         routing_key=routing_key,
14                         body=message)
15   print(" [x] Sent %r:%r" % (routing_key, message))
16   connection.close()
  • 消费者
1 import pika
 2   import sys
 3     
 4   connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
 5   channel = connection.channel()
 6     
 7   channel.exchange_declare(exchange='topic_logs',
 8                            exchange_type='topic')
 9     
10   result = channel.queue_declare(exclusive=True)
11   queue_name = result.method.queue
12     
13   binding_keys = sys.argv[1:]
14   if not binding_keys:
15       sys.stderr.write("Usage: %s [binding_key]...\n" % sys.argv[0])
16       sys.exit(1)
17     
18   for binding_key in binding_keys:
19       channel.queue_bind(exchange='topic_logs',
20                          queue=queue_name,
21                          routing_key=binding_key)
22     
23   print(' [*] Waiting for logs. To exit press CTRL+C')
24     
25   def callback(ch, method, properties, body):
26       print(" [x] %r:%r" % (method.routing_key, body))
27     
28   channel.basic_consume(callback,
29                         queue=queue_name,
30                         no_ack=True)
31     
32   channel.start_consuming()
  • 测试
  • 接收所有日志
  • python comsumer.py "#"
  • 接收包含kern开头的
  • python comsumer.py "kern.*"
  • 接收critical结尾的
  • python comsumer.py "*.critical"
  • 发送kern.critical、A critical kernel error
  • python producer.py "kern.critical" "A critical kernel error"

基于RabbitMQ的RPC

  • 何为RPC
  • 客户端通过消息队列向服务端发送数据
  • 服务端处理完数据,将数据通过回调队列返回给客户端
  • 客户端可能回同时发起多个任务,在服务端回调后应当根据唯一标识为每一个任务返回值的指定数据

python rabbitmq接收消息 python连接rabbitmq_RPC_05

  • 服务端
1 import pika
 2     
 3   connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
 4     
 5   channel = connection.channel()
 6     
 7   channel.queue_declare(queue='rpc_queue')
 8     
 9   def fib(n):
10       if n == 0:
11           return 0
12       elif n == 1:
13           return 1
14       else:
15           return fib(n-1) + fib(n-2)
16     
17   def on_request(ch, method, props, body):
18       n = int(body)
19     
20       print(" [.] fib(%s)" % n)
21       response = fib(n)
22     
23       ch.basic_publish(exchange='',
24                        routing_key=props.reply_to,
25                        properties=pika.BasicProperties(correlation_id = \
26                                                            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(on_request, queue='rpc_queue')
32     
33   print(" [x] Awaiting RPC requests")
34   channel.start_consuming()
  • 客户端
1 import pika
 2   import uuid
 3     
 4   class FibonacciRpcClient(object):
 5       def __init__(self):
 6           self.connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
 7     
 8           self.channel = self.connection.channel()
 9     
10           result = self.channel.queue_declare(exclusive=True)
11           self.callback_queue = result.method.queue
12     
13           self.channel.basic_consume(self.on_response, no_ack=True,
14                                      queue=self.callback_queue)
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     
36   print(" [x] Requesting fib(30)")
37   response = fibonacci_rpc.call(30)
38   print(" [.] Got %r" % response)