路由

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

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

绑定

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

channel.queue_bind(exchange=exchange_name,
queue=queue_name)
  • 1
  • 2

绑定是一个交易所和一个队列之间的关系。这可以解释为:一个队列对源于这个交易所的消息感兴趣。 
绑定可以采用一个额外的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')
  • 1
  • 2
  • 3

一个绑定键的意义取决于交易所类型。我们先前使用过的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')
  • 1
  • 2

准备好发送消息:

channel.basic_publish(exchange='direct_logs',
routing_key=severity,
body=message)
  • 1
  • 2
  • 3

为了使事情简单我们假设’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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

整合

 
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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

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

生成日志: 
 
查看日志文件确实只收到了error日志: 

基于Python语言使用RabbitMQ消息队列(四)的更多相关文章

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

    远程过程调用(RPC) 在第二节里我们学会了如何使用工作队列在多个工人中分布时间消耗性任务. 但如果我们想要运行存在于远程计算机上的方法并等待返回结果该如何去做呢?这就不太一样了,这种模式就是常说的远 ...

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

    Topics 在前面教程中我们改进了日志系统,相比较于使用fanout类型交易所只能傻瓜一样地广播,我们用direct获得了选择性接收日志的能力. 虽然使用direct类型交易所改进了我们的系统,但它 ...

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

    介绍 RabbitMQ 是一个消息中间人(broker): 它接收并且发送消息. 你可以把它想象成一个邮局: 当你把想要寄出的信放到邮筒里时, 你可以确定邮递员会把信件送到收信人那里. 在这个比喻中, ...

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

    发布/订阅 前面的教程中我们已经创建了一个工作队列.在一个工作队列背后的假设是每个任务恰好会传递给一个工人.在这一部分里我们会做一些完全不同的东西——我们会发送消息给多个消费者.这就是所谓的“发布/订 ...

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

    工作队列 在第一节我们写了程序来向命名队列发送和接收消息 .在本节我们会创建一个工作队列(Work Queue)用来在多个工人(worker)中分发时间消耗型任务(time-consuming tas ...

  6. python学习之-- RabbitMQ 消息队列

    记录:异步网络框架:twisted学习参考:www.cnblogs.com/alex3714/articles/5248247.html RabbitMQ 模块 <消息队列> 先说明:py ...

  7. Python并发编程-RabbitMQ消息队列

    RabbitMQ队列 RabbitMQ是一个在AMQP基础上完整的,可复用的企业消息系统.他遵循Mozilla Public License开源协议. MQ全称为Message Queue, 消息队列 ...

  8. Python RabbitMQ消息队列

    python内的队列queue 线程 queue:不同线程交互,不能夸进程 进程 queue:只能用于父进程与子进程,或者同一父进程下的多个子进程,进行交互 注:不同的两个独立进程是不能交互的.   ...

  9. 基于ASP.NET Core 5.0使用RabbitMQ消息队列实现事件总线(EventBus)

    文章阅读请前先参考看一下 https://www.cnblogs.com/hudean/p/13858285.html 安装RabbitMQ消息队列软件与了解C#中如何使用RabbitMQ 和 htt ...

随机推荐

  1. SqlHelper简单实现(通过Expression和反射)3.实体,数据传输对象(DTO)Helper类设计

    EntityHelper的主要功能有: 1.通过反射获取DTO的字段,主要提供给在需要从Entity获取数据后,填充给DTO并返回的作用: 通过反射获取PropertyInfo[]对象,然后取出Nam ...

  2. $《第一行代码:Android》读书笔记——第1章 Android系统

    (一)Android系统架构 1.Linux内核层:各种底层驱动,如显示驱动.音频驱动.电源管理等. 2.系统运行库层:各种库支持,如3D绘图.浏览器内核.数据库等. 3.应用框架层:各种API,各种 ...

  3. 递归实现N皇后问题

    其实是看到一位名为“活在二次元的伪触”的博主昨天还是前天写了篇这个题材的笔记,觉得有点意思,于是想自己来写写. 其实我发现上述那位同学写N皇后问题写得还不错,文末也会给出这位同学用通过递归的方法实现N ...

  4. Efficient Vector Representation for Documents through Corruption-by Minmin Chen阅读

    关键词: 词向量.文档向量.文档表示 地址:https://openreview.net/forum?id=B1Igu2ogg&noteId=B1Igu2ogg 首先,论文解决的是Word2V ...

  5. maven 一个简单项目 —— maven权威指南学习笔记(三)

    目标: 对构建生命周期 (build  lifecycle),Maven仓库 (repositories),依赖管理 (dependency management)和项目对象模型 (Project O ...

  6. ZooKeeper-安装和运行

    ZooKeeper安装和运行 1. 下载安装包 zookeeper-3.4.9.tar.gz 2. 解压 tar -zxvf zookeeper-3.4.9.tar.gz ZooKeeper提供了几个 ...

  7. Phoenix性能优化

    目录: 1.建表优化 2.二级索引 3.并行处理 1.建表优化 Salting 翻译成中文是加盐的意思,本质是在hbase的rowkey的byte数组的第一个字节位置设定一个系统生成的byte值, 这 ...

  8. 安装,配置webpack.

    1.下载node.js 2.在需要用到webpack的项目下打开命令窗口运行npm init生成package.js 3.安装webpack,使用npm install webpack --save- ...

  9. Django中间件的总结

    一.中间件 --中间件是一个轻量级.底层的插件系统,可以加入Django的请求和响应过程,修改Django的输入和输出 --每一个中间件组件是一个独立的Python类,可以定义下面方法中的一个和多个 ...

  10. keystone uwsgi failed

    ~$ /usr/local/bin/uwsgi /etc/keystone/keystone-uwsgi-public.ini[uWSGI] getting INI configuration fro ...