关闭

基于Python语言使用RabbitMQ消息队列(四)

标签: RabbitMQpython日志系统路由
261人阅读 评论(0) 收藏 举报
分类:

路由

在上一节我们构建了一个简单的日志系统。我们能够广播消息给很多接收者。

在本节我们将给它添加一些特性——我们让它只订阅所有消息的子集。例如,我们只把严重错误(critical error)导入到日志文件(存入磁盘空间),但仍然可以打印所有日志消息到控制台。

绑定

前面的例子中我们已经创建了绑定,像下面这样:

channel.queue_bind(exchange=exchange_name,
                   queue=queue_name)

绑定是一个交易所和一个队列之间的关系。这可以解释为:一个队列对源于这个交易所的消息感兴趣。
绑定可以采用一个额外的routing_key 参数。为避免同basic_publish参数混淆,我们称呼它为绑定键(binding key)。我们用一个键来创建一个绑定This is how we could create a binding with a key:

channel.queue_bind(exchange=exchange_name,
                   queue=queue_name,
                   routing_key='black')

一个绑定键的意义取决于交易所类型。我们先前使用过的fanout类型交易所就会忽略它的值。

直接型交易所(Direct exchange)

我们先前的日志系统会广播所有消息给所有消费者。我们现在想扩展它让过滤掉一些消息,基于这些消息的严重级别。例如我们可能想要向磁盘写日志的脚本只接收严重错误critical error,不要浪费磁盘空间在warning或info日志上面。

我们正使用的fanout类型交易所不会给我们太大的灵活性——它只能够无意识地进行广播。

我们会使用直接型交易所进行替代,直接型交易所背后的路由算法很简单——一条消息会前往绑定键(binding key)恰巧匹配这条消息的路由键(routing key)的队列。
为了阐释这个问题,考虑下图的设定:
这里写图片描述
在这个设定当中我们看到直接型交易所X有两个队列与之绑定。第一个队列的绑定键为“orange”,第二个有两个绑定键,一个是“black”,另一个是“green”。

在这个设定中,发布到交易所中的带有路由键“orange”的会被路由到队列Q1。带有路由键“black”和“green”的会前往Q2。所有其他的消息会被忽略。

多重绑定

这里写图片描述
使用相同的绑定键绑定多个队列完全没有问题。在我们的例子中我们可以用绑定键“black”在交易所X和队列Q1之间添加绑定。这样的话,direct型交易所就会表现的像fanout交易所,广播消息给所有匹配的队列。具有“black”路由键的消息会被传送给Q1和Q2。

生成日志

我们会为日志系统使用这个模型。发送消息到direct交易所,而非fanout交易所。我们会提供日志级别(log severity)作为路由键。这样接收脚本就能够选择它想要的级别来接收。我们首先关注生成日志。

像通常我们需要创建一个交易所时那样:

channel.exchange_declare(exchange='direct_logs',
                         type='direct')

准备好发送消息:

channel.basic_publish(exchange='direct_logs',
                      routing_key=severity,
                      body=message)

为了使事情简单我们假设’severity’ 是 ‘info’, ‘warning’, ‘error’中的一种。

订阅

接收消息就跟之前的教程中一样,不同的是——我们要为每种severity创建一个新的绑定。

result = channel.queue_declare(exclusive=True)
queue_name = result.method.queue

for severity in severities:
    channel.queue_bind(exchange='direct_logs',
                       queue=queue_name,
                       routing_key=severity)

整合

这里写图片描述
emit_log_direct.py完整代码:

#!/usr/bin/env python
import pika
import sys

connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = connection.channel()

channel.exchange_declare(exchange='direct_logs',
                         type='direct')

severity = sys.argv[1] if len(sys.argv) > 2 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()

receive_logs_direct.py完整代码:

#!/usr/bin/env python
import pika
import sys

connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = connection.channel()

channel.exchange_declare(exchange='direct_logs',
                         type='direct')

result = channel.queue_declare(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(callback,
                      queue=queue_name,
                      no_ack=True)

channel.start_consuming()

我在自己的Ubuntu终端开启了三个控制台,两个用来接收日志消息,其中一个设置为只接收error日志,并把收到的日志存入日志文件。另一个接收info,warning和error,直接打印到屏幕。如下图:
写入文件:
这里写图片描述
打印到屏幕:
这里写图片描述

生成日志:
这里写图片描述
查看日志文件确实只收到了error日志:
这里写图片描述

0
0
查看评论

基于Python语言使用RabbitMQ消息队列(五)

Topics在前面教程中我们改进了日志系统,相比较于使用fanout类型交易所只能傻瓜一样地广播,我们用direct获得了选择性接收日志的能力。虽然使用direct类型交易所改进了我们的系统,但它仍然有所限制——它不能做基于多重条件(multiple criteria)的路由。 在日志系统中我们可...
  • zhangfh1990
  • zhangfh1990
  • 2017-05-26 15:46
  • 228

基于Python语言使用RabbitMQ消息队列(一)

介绍RabbitMQ 是一个消息中间人(broker): 它接收并且发送消息. 你可以把它想象成一个邮局: 当你把想要寄出的信放到邮箱里时, 你可以确定邮递员会把信送到收信人那里. 在这个比喻中, RabbitMQ 就是一个邮箱, 同时也是一个邮局和邮递员 . 和邮局的主要不同点在于Rabbi...
  • zhangfh1990
  • zhangfh1990
  • 2017-05-24 14:55
  • 358

基于Python语言使用RabbitMQ消息队列(六)

远程过程调用(RPC)在第二节里我们学会了如何使用工作队列在多个工人中分布时间消耗性任务。 但如果我们想要运行存在于远程计算机上的方法并等待返回结果该如何去做呢?这就不太一样了,这种模式就是常说的远程过程调用(RPC)。 在本节我们会在本节我们会使用RabbitMQ创建一个RPC系统:一个客户端...
  • zhangfh1990
  • zhangfh1990
  • 2017-05-26 22:50
  • 224

基于Python语言使用RabbitMQ消息队列(二)

工作队列在第一节我们写了程序来向命名队列发送和接收消息 。在本节我们会创建一个工作队列(Work Queue)用来在多个工人(worker)中分发时间消耗型任务(time-consuming tasks)。工作队列(又叫做: Task Queues)背后的主体思想是 避免立刻去执行耗时任务并且等待它...
  • zhangfh1990
  • zhangfh1990
  • 2017-05-24 15:50
  • 353

基于Python语言使用RabbitMQ消息队列(三)

发布/订阅前面的教程中我们已经创建了一个工作队列。在一个工作队列背后的假设是每个任务恰好会传递给一个工人。在这一部分里我们会做一些完全不同的东西——我们会发送消息给多个消费者。这就是所谓的“发布/订阅”模式。为了解释这种模式,我们将会构建一个简单的日志系统。它包含两个程序——第一个产生日志消息,第二...
  • zhangfh1990
  • zhangfh1990
  • 2017-05-25 17:54
  • 855

RabbitMQ消息队列(四):分发到多Consumer(Publish/Subscribe)(转)

上篇文章中,我们把每个Message都是deliver到某个Consumer。在这篇文章中,我们将会将同一个Message deliver到多个Consumer中。这个模式也被成为 "publish / subscribe"。     这篇文章中,...
  • tantexian
  • tantexian
  • 2015-03-31 13:44
  • 1191

总结消息队列RabbitMQ的基本用法

AMQP ,即Advanced Message Queuing Protocol,高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。消息中间件主要用于组件之间的解耦,消息的发送者无需知道消息使用者的存在,反之亦然。 AMQP的主要特征是面向消息、队列、路由(包括点...
  • not_give_up_
  • not_give_up_
  • 2017-03-30 10:39
  • 1125

C#.NET使用消息队列RabbitMQ

一、概念。 此处不对概念进行阐述,搜一下有很多,英语能力不错的,建议到官网去看。 RabbitMQ:http://www.rabbitmq.com/ 例子请在页面中搜索:Tutorials,别急着看例子,先完成安装与配置。 二、安装Erlang。     由于...
  • q18665401
  • q18665401
  • 2016-10-17 09:17
  • 894

RabbitMQ消息队列的总结

什么是消息队列? MQ全称为MessageQueue,消息队列(MQ)是一种应用程序对应用程序的通信方法。应用程序通过写和检索出入列队的针对应用程序的数据(消息)来通信,而无需专用连接来链接它们。消息传递指的是程序之间通过在消息中发送数据进行通信,而不是通过直接调用彼此来通信,直接调用通常是用于诸如...
  • hr787753
  • hr787753
  • 2017-02-21 08:58
  • 453

开源稳定的消息队列 RabbitMQ

http://www.cnblogs.com/shanyou/archive/2012/10/27/2742979.html RabbitMQ是一个在AMQP协议标准基础上完整的,可服用的企业消息系统。他遵循Mozilla Public License开源协议。采用 Erlang 实现的工...
  • mituan1234567
  • mituan1234567
  • 2015-08-12 17:24
  • 624
    个人资料
    • 访问:9657次
    • 积分:360
    • 等级:
    • 排名:千里之外
    • 原创:13篇
    • 转载:5篇
    • 译文:14篇
    • 评论:3条