在上一教程中,我们改进了日志记录系统。 我们没有使用只能进行虚拟广播的fanout交换器,而是使用直接交换器,并有可能选择性地接收日志。

尽管使用直接交换改进了我们的系统,但它仍然存在局限性-它不能基于多个条件进行路由。

在我们的日志记录系统中,我们可能不仅要根据严重性订阅日志,还要根据发出日志的源订阅日志。 您可能从syslog unix工具中了解了这个概念,该工具根据严重性(info / warn / crit ...)和工具(auth / cron / kern ...)路由日志。

这将为我们提供很大的灵活性-我们可能只想听来自“ cron”的严重错误,也可以听“ kern”的所有日志。

为了在日志系统中实现这一点,我们需要学习更复杂的topic交换器。

Topic交换器

发送到主题交换的消息不能具有任意的routing_key-它必须是单词列表,以.分隔。 这些词可以是任何东西,但是通常它们指定与消息相关的某些功能。 一些有效的路由关键示例:“ stock.usd.nyse”,“ nyse.vmw”,“ quick.orange.rabbit”。 路由密钥中可以包含任意多个单词,最多255个字节。

绑定键也必须采用相同的形式。 topic交换器背后的逻辑类似于direct交换器的逻辑-使用特定路由键发送的消息将被传递到所有使用匹配绑定键绑定的队列。 但是,绑定键有两个重要的特殊情况:

  • *(星号)可以代替一个单词。

  • #(哈希)可以替代零个或多个单词。

在一个示例中最容易解释这一点:

在此示例中,我们将发送所有描述动物的消息。 将使用包含三个词(两个点)的路由键发送消息。 路由键中的第一个单词将描述速度,第二个描述颜色,第三个描述物种:“ ..”。

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

这些绑定可以总结为:

  • Q1对所有橙色动物都感兴趣。
  • Q2想知道有关兔子的一切,以及有关懒惰动物的一切。

路由键设置为“ quick.orange.rabbit”的消息将传递到两个队列。 消息“ lazy.orange.elephant”也将发送给他们两个。 另一方面,“ quick.orange.fox”将仅进入第一个队列,而“ lazy.brown.fox”将仅进入第二个队列。 即使“ lazy.pink.rabbit”与两个绑定匹配,也只会传递到第二个队列一次。 “ quick.brown.fox”与任何绑定都不匹配,因此将被丢弃。

如果我们违约并发送一个或四个单词的消息,例如“ orange”或“ quick.orange.male.rabbit”,会发生什么? 好吧,这些消息将不匹配任何绑定,并且将会丢失。

另一方面,“ lazy.orange.male.rabbit”即使有四个单词,也将匹配最后一个绑定,并将其传送到第二个队列。

Topic交换器功能强大,可以像其他交流一样进行。

当队列用“#”(哈希)绑定键绑定时,它将接收所有消息,而与路由键无关,就像在fanout交换器中一样。

所有代码

我们将在日志记录系统中使用topic交换器。 我们将从一个可行的假设开始,即日志的路由键将包含两个词:“ .”。

# emit_log_topic.go
package main import (
"log"
"os"
"strings" "github.com/streadway/amqp"
) func failOnError(err error, msg string) {
if err != nil {
log.Fatalf("%s: %s", msg, err)
}
} func main() {
conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/")
failOnError(err, "Failed to connect to RabbitMQ")
defer conn.Close() ch, err := conn.Channel()
failOnError(err, "Failed to open a channel")
defer ch.Close() err = ch.ExchangeDeclare(
"logs_topic", // name
"topic", // type
true, // durable
false, // auto-deleted
false, // internal
false, // no-wait
nil, // arguments
)
failOnError(err, "Failed to declare an exchange") body := bodyFrom(os.Args)
err = ch.Publish(
"logs_topic", // exchange
severityFrom(os.Args), // routing key
false, // mandatory
false, // immediate
amqp.Publishing{
ContentType: "text/plain",
Body: []byte(body),
})
failOnError(err, "Failed to publish a message") log.Printf(" [x] Sent %s", body)
} func bodyFrom(args []string) string {
var s string
if (len(args) < 3) || os.Args[2] == "" {
s = "hello"
} else {
s = strings.Join(args[2:], " ")
}
return s
} func severityFrom(args []string) string {
var s string
if (len(args) < 2) || os.Args[1] == "" {
s = "anonymous.info"
} else {
s = os.Args[1]
}
return s
}

获取所有日志

#shell 1
go run receive_logs_topic.go "#"

要从设施“ kern”接收所有日志:

#shell 1
go run receive_logs_topic.go "kern.*"

或者,如果您只想听听“critical”日志:

#shell 1
go run receive_logs_topic.go "*.critical"

您可以创建多个绑定:

#shell 1
go run receive_logs_topic.go "kern.*" "*.critical"

并发出带有路由键“ kern.critical”的日志:

#shell 1
go run emit_log_topic.go "kern.critical" "A critical kernel error"

RabbitMQ官方教程五 Topic(GOLANG语言实现)的更多相关文章

  1. RabbitMQ官方教程四 Routing(GOLANG语言实现)

    在上一教程中,我们构建了一个简单的日志记录系统. 我们能够向许多消费者广播日志消息. 在本教程中,我们将向其中添加功能-我们将使仅订阅消息的子集成为可能. 例如,我们将只能将严重错误消息定向到日志文件 ...

  2. RabbitMQ官方教程三 Publish/Subscribe(GOLANG语言实现)

    RabbitMQ官方教程三 Publish/Subscribe(GOLANG语言实现) 在上一个教程中,我们创建了一个工作队列. 工作队列背后的假设是,每个任务都恰好交付给一个worker处理. 在这 ...

  3. RabbitMQ官方教程二 Work Queues(GOLANG语言实现)

    RabbitMQ官方教程二 Work Queues(GOLANG语言实现) 在第一个教程中,我们编写了程序来发送和接收来自命名队列的消息. 在这一部分中,我们将创建一个工作队列,该队列将用于在多个wo ...

  4. RabbitMQ入门教程(五):扇形交换机发布/订阅(Publish/Subscribe)

    原文:RabbitMQ入门教程(五):扇形交换机发布/订阅(Publish/Subscribe) 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. ...

  5. 第 五 课 golang语言变量

    1 变量三种声明: (第一种的var和类型都是多余: 第二种最简洁,但是第二种只能用在函数中,不能是全局变量的声明)        第一种: var v_name v_type(注意顺序) v_nam ...

  6. RabbitMQ官方教程一Hello World(GOLANG语言实现)

    介绍 RabbitMQ是消息中间件:它接受并转发消息. 您可以将其视为邮局系统:将要发送的邮件放在邮箱中时, 可以确保邮递员最终将邮件传递给收件人. 以此类推,RabbitMQ是一个邮箱,一个邮局和一 ...

  7. RabbitMQ+PHP教程

    RabbitMQ+PHP 教程一(Hello World) RabbitMQ+PHP 教程二(Work Queues) RabbitMQ+PHP 教程三(Publish/Subscribe) Rabb ...

  8. 如何从40亿整数中找到不存在的一个 webservice Asp.Net Core 轻松学-10分钟使用EFCore连接MSSQL数据库 WPF实战案例-打印 RabbitMQ与.net core(五) topic类型 与 headers类型 的Exchange

    如何从40亿整数中找到不存在的一个 前言 给定一个最多包含40亿个随机排列的32位的顺序整数的顺序文件,找出一个不在文件中的32位整数.(在文件中至少确实一个这样的数-为什么?).在具有足够内存的情况 ...

  9. OpenGL官方教程——着色器语言概述

    OpenGL官方教程——着色器语言概述 OpenGL官方教程——着色器语言概述 可编程图形硬件管线(流水线) 可编程顶点处理器 可编程几何处理器 可编程片元处理器 语言 可编程图形硬件管线(流水线) ...

随机推荐

  1. 2017.10.2 国庆清北 D2T2 树上抢男主

    /* 我只看懂了求LCA */ #include<iostream> #include<cstring> #include<cstdio> #include< ...

  2. 深入基础(二)练习题,REPL交互解析器

    NPM     关于npm命令其实不算很多很多,起码比dos命令少不少呢废话少说npm命令大全and各个命令用处持续更新中..来自园子内另外一位大神~:http://www.cnblogs.com/P ...

  3. python中isinstance函数

    1.描述 python中isinstance()函数,是python中的一个内置函数,用来判断一个函数是否是一个已知的类型,类似type(). 2.语法 isinstance(object,class ...

  4. Pro自定义数据源原理

    1.  概念 Connector:定义连接到一个数据源的连接信息,用于创建datastore. Datastore:代表一个数据源的实例,用于打开一个或多个tables或feature class. ...

  5. golang 常见变成问题01

    Golang常见编程问题 --语言简单 func CopyFile (dst, src string) (w int64, err error) { srcFile, err := os.Open ( ...

  6. SpringData like关键字不起作用

    使用springdata简单查询时,like关键字不起作用 Hibernate: select article0_.oId as oId1_2_, article0_.articleAbstract ...

  7. 膜态沸腾UDF【转载】

    膜态沸腾的UDF,添加注释.其中获取VOF梯度的方法详见前面的日志,其中很多宏无法通过UDF手册查阅, 蒸汽相中的质量源项的一般形式为: 式中: 通过一阶近似,热流之差可表达为: 式中: 通过此近似, ...

  8. mac安装rust的pyo3模块

    Rust 发布的工具链包括了 stable.beta 和 nightly 三种不同版本. nightly 是最激进的版本,包含了大量(可能不稳定)的新/高级特性.stable 版本目前可能还不支持一些 ...

  9. ubuntu之路——day3(本来打算做pytorch的练习 但是想到前段时间的数据预处理的可视化分析 就先总结一下)

    首先依托于一个场景来进行可视化分析 直接选了天池大数据竞赛的新人赛的一个活跃题目 用的方式也是最常用的数据预处理方式 [新人赛]快来一起挖掘幸福感!https://tianchi.aliyun.com ...

  10. 深度学习面试题12:LeNet(手写数字识别)

    目录 神经网络的卷积.池化.拉伸 LeNet网络结构 LeNet在MNIST数据集上应用 参考资料 LeNet是卷积神经网络的祖师爷LeCun在1998年提出,用于解决手写数字识别的视觉任务.自那时起 ...