Topics

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

虽然使用direct类型交易所改进了我们的系统,但它仍然有所限制——它不能做基于多重条件(multiple criteria)的路由。 
在日志系统中我们可能不只是想要基于严重级别来订阅日志。也想要基于产生日志的来源。你可能从unix的系统日志工具(syslog unix tool)知道了这个概念,它就是基于严重级别 (info/warn/crit…)和设施(auth/cron/kern…)来路由日志的。 
这会给我们很大灵活性——我们可能只想监听来自于‘cron’的严重错误(critical errors)和来自‘kern’的所有日志。 
为了在我们的日志系统中实现这个功能我们需要了解更复杂的topic类型交易所。

Topic 交易所

发往topic类型交易所的消息不能只有一个独断的路由键(routing_key)——它必须是个词汇列表,词与词之间由‘.’来界定。可以是任何词汇,但通常它们指定了一些与消息相关联的特性。一些有效的路由键例子:”stock.usd.nyse”, “nyse.vmw”, “quick.orange.rabbit”,只要你想,在路由键里可以加尽可能多的词汇,上限是255 bytes。

绑定键必须是同样的形式。topic交易所背后的逻辑与direct类似——使用特定路由键发送的消息会传递给所有拥有匹配的绑定键的队列。但对于绑定键有两种重要的特殊情形:

“*” (star) 正好代替一个词. 
“#” (hash) 能代替零个或多个词.

可以很容易地用一个例子解释: 
 
在这个例子中我们发送的消息都是描述动物的。将要发送的消息的路由键包含三个词(两个点号)。第一个词描述的是敏捷性,第二个词是颜色,第三个词是种类:“<敏捷性>.<颜色>.<种类>”。

我们创建了三个绑定: Q1 绑定键是 “.orange.” , Q2 是 “..rabbit” 和 “lazy.#”.

这些绑定可以总结为:

  • Q1 对所有橙色(orange)动物感兴趣.
  • Q2想要知道关于rabbits的每件事情, 和关于lazy 类型动物的所有.

路由键设置为 “quick.orange.rabbit” 的消息会同时传送给两个队列。消息”lazy.orange.elephant” 也会传送给两个队列。”quick.orange.fox”会传送给第一个队列。”lazy.brown.fox”只会传送给第二个队列。”quick.brown.fox” 不匹配任何绑定,所以它会被忽略。

如果我们破坏约定,发送带有一个词或四个词的消息绑定,像”orange”或者”quick.orange.male.rabbit”,会发生什么呢?当然,由于这些消息不匹配任何绑定会被丢失。

另一方面即便 “lazy.orange.male.rabbit”, 有4个词,但它匹配最后一个绑定,所以它会被传送给第二个队列。

Topic 交易所

Topic 交易所很强大并且可以拥有其他类型交易所的的表现 
当一个队列使用了“#”绑定键它就会接收所有消息,不管是什么路由键。此时就像是fanout类型交易所。 当在绑定中没有使用特殊字符 “*” 
(star) 和 “#” (hash) topic交易所就跟direct交易所一样。

整合

我们将在日志系统中使用topic交易所。假设日志的路由键有两个词 “场所.严重级别”。

代码同之前的教程中几乎相同

emit_log_topic.py完整代码:

#!/usr/bin/env python
import pika
import sys connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = connection.channel() channel.exchange_declare(exchange='topic_logs',
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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

receive_log_topic.py完整代码:

#!/usr/bin/env python
import pika
import sys connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = connection.channel() channel.exchange_declare(exchange='topic_logs',
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(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终端开启了四个控制台,其中三个接收日志,日志的接收和发送情况如图: 
接收所有日志 

接收级别为critical日志 

接收产生自kernel日志 

日志的发送 

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

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

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

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

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

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

    路由 在上一节我们构建了一个简单的日志系统.我们能够广播消息给很多接收者. 在本节我们将给它添加一些特性——我们让它只订阅所有消息的子集.例如,我们只把严重错误(critical error)导入到日 ...

  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. loadrunner之脚本篇——代理录制

    版本:Loadruner 11.0 A.PC端录制Web应用程序 步骤1:根据实际情况,选择对应的协议 本例中选择Web(HTTP/HTML),如下 步骤2:找到代理设置界面 点击 Start Rec ...

  2. OC导入框架方式#import、@import的区别

    #import负责导入程序所需的文件的信息导入到程序中,随着程序所需的文件越来越多,程序就要导入更多的文件,这就带来了越来越长的编译时间,而且有大量重复的.为了解决这个问题可以采用以下办法解决,创建. ...

  3. springboot打war包

    修改pom为war不是jar. 移除tomcar的jar依赖: <dependency> <groupId>org.springframework.boot</group ...

  4. Django-虚拟环境设置

    Django 虚拟环境virtualenv virtualenv是用来处理多个用python语言进行开发的项目,在同一台机器上部署,不同项目依赖不同第三方库版本所造成的问题. 打个比方,现在你机器上要 ...

  5. P4271 [USACO18FEB]New Barns

    题目 P4271 [USACO18FEB]New Barns 做法 这题很长见识啊!! 知识点:两棵树\((A,B)\)联通后,新树的径端点为\(A\)的径端点与\(B\)的径端点的两点 不断加边,那 ...

  6. list— 把数组中的值赋给一组变量

    (PHP 4, PHP 5, PHP 7) list — 把数组中的值赋给一组变量 array list ( mixed $var1 [, mixed $... ] ) 像 array() 一样,这不 ...

  7. Django 组合索引

    TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join( ...

  8. vmxnet3 丢包处理

    https://vswitchzero.com/2017/09/26/vmxnet3-rx-ring-buffer-exhaustion-and-packet-loss/

  9. js学习笔记1(变量、作用域、内存)

    写在前面,舍弃叽叽歪歪,只做学习笔记,认真踏实. 学习书籍:javascript高级程序设计3版. 章节4.1 基本类型和引用类型 1.基本类型在内存中占据固定大小的空间,所以保存在栈内存中. 2.从 ...

  10. 算法总结之 数组的partition调整 三个值的升序

    给定一个数组arr, 其中只可能有 0,1,2三个值,请实现arr排序 另一种问法: 有一个数组,只有红 蓝 黄 球,请事先红球全放在数组的左边,蓝球放中间,黄球放右边 另一种问法: 有一个数组,再给 ...