RabbitMQ --- Publish/Subscribe(发布/订阅)
目录
RabbitMQ --- Hello Mr.Tua
RabbitMQ --- Work Queues(工作队列)
RabbitMQ --- Routing(路由)
前言
在第二篇文章中介绍了 Work Queues(工作队列),它适用于把一个消息发送给一个 Consumer 去处理的场景,也就是说每个 Consumer 都是处理不同的消息,如果某个 Consumer 挂了才会把未完成或没有处理的消息转发给其它的 Consumer 去处理。假如要把一个消息发送给多个 Consumer 去处理,也就是说每个 Consumer 都是处理相同的消息,这种场景就需要用到发布/订阅(Publish/Subscribe)模式,即 Producer 为发布者,Consumer 为订阅者。
匿名交换机(Nameless exchange)
Exchange 被称为交换机,担任中转站的职责,其工作原理是 Producer 先把消息发送给 Exchange,然后再由 Exchange 指定消息按照路由规则进入队列转发给 Consumer 去处理。在前两篇文章的示例中其实已经用到了默认的 Exchange,即匿名交换机(Nameless exchange)。
/*exchange:指定空字符串表示默认的Exchange标识 | routingKey:指定消息发送到哪个队列*/
channel.BasicPublish(exchange, routingKey, basicProperties, body)
交换机的类型(Exchange types)
Exchange 必须要知道如何处理它接收到的每个消息,是否让消息进入指定的队列?是否让消息进入多个队列?是否直接忽略消息?这些都取决于它的四种类型。
1.Direct:处理路由键。需要将一个队列绑定到 Exchange 上,只允许该消息与一个特定的路由键名称完整匹配才能被转发给队列。
/*Producer*/ //定义交换机
channel.ExchangeDeclare
(
exchange: "Tua",
type: ExchangeType.Direct//类型
); channel.BasicPublish
(
exchange: "Tua",
routingKey: "Mr.Tua",//路由键名称
basicProperties: null,
body: body
);
/*Consumer*/ //定义交换机
channel.ExchangeDeclare
(
exchange: "Tua",
type: ExchangeType.Direct
); //绑定交换机和队列,指明如何转发消息给队列
channel.QueueBind
(
queue: queueName,
exchange: "Tua",
routingKey: "Mr.Tua"//此处和生产者的路由键作比较,相同则转发消息,反之则不转发
);
2.Fanout:不处理路由键。只要将队列绑定到 Exchange 上,Producer 发送到 Exchange 的消息都会被广播到所有的队列上。
/*Producer*/ channel.ExchangeDeclare
(
exchange: "Tua",
type: ExchangeType.Fanout
); channel.BasicPublish
(
exchange: "Tua",
routingKey: string.Empty,//此处若有值则会忽略
basicProperties: null,
body: body
);
/*Consumer*/ channel.ExchangeDeclare
(
exchange: "Tua",
type: ExchangeType.Fanout
); //绑定交换机和队列,指明如何转发消息给队列
channel.QueueBind
(
queue: queueName,
exchange: "Tua",
routingKey: string.Empty//此处若有值则会忽略
);
3.Topic:将路由键和某种命名规则进行匹配,只允许匹配上的消息才能被转发给队列。符号“#”匹配一个或多个词,符号“*”匹配一个词。
/*Producer*/ channel.ExchangeDeclare
(
exchange: "Tua",
type: ExchangeType.Topic
); channel.BasicPublish
(
exchange: "Tua",
routingKey: "Mr.Tua.Tua"
basicProperties: null,
body: body
);
/*Consumer*/ channel.ExchangeDeclare
(
exchange: "Tua",
type: ExchangeType.Topic
); //绑定交换机和队列,指明如何转发消息给队列
channel.QueueBind
(
queue: queueName,
exchange: "Tua",
routingKey: "Mr.#"//符号#可以匹配上Mr.Tua.Tua,符号*只能匹配上Mr.Tua
);
4.Headers:它不依赖路由键,而是在接收方绑定队列和 Exchange 时指定键值对和发送方 headers 属性中的键值对进行匹配,键值对的值可以是任何类型,只允许匹配上的消息才能被转发给队列。匹配规则 x-match 有两种类型:all 表示所有的键值对匹配;any 表示至少有一个键值对匹配。
/*Producer*/ channel.ExchangeDeclare
(
exchange: "Tua",
type: ExchangeType.Headers
);
var headers = new Dictionary<string, object>();//定义键值对集合
headers.Add("Name", "Mr.Tua");
headers.Add("Age", );
var basicProperties = channel.CreateBasicProperties();
basicProperties.Headers = headers;//绑定消息中的headers属性值 channel.BasicPublish
(
exchange: "Tua",
routingKey: string.Empty,
basicProperties: basicProperties,
body: body
);
/*Consumer*/ channel.ExchangeDeclare
(
exchange: "Tua",
type: ExchangeType.Headers
);
var headers = new Dictionary<string, object>();//定义键值对集合
headers.Add("x-match", "any");//定义匹配规则
headers.Add("Name", "Mr.Tua.Tua");
headers.Add("Age", ); channel.QueueBind
(
queue: queueName,
exchange: "Tua",
routingKey: string.Empty,
arguments: headers//指定键值对
);
临时队列(Temporary queues)
当希望在生产者和消费者之间共享队列时,为队列命名是很重要的。如果希望接收所有最新的消息时,那么就可以不用关心队列名称了,需要一个新的空队列,而且当 Consumer 和 Rabbit 服务连接断开时需要自动删除该队列,这就是临时队列(Temporary queues)的作用。
string queueName = channel.QueueDeclare().QueueName;//创建一个随机命名的唯一非持久可以自动删除的临时队列
完整示例
现在修改上一章的代码,通过 Fanout Exchange 使两个 Consumer 接收相同的消息:
using RabbitMQ.Client;
using System;
using System.Text; namespace Producer
{
class Program
{
static void Main(string[] args)
{
var factory = new ConnectionFactory
{
HostName = "10.202.228.107",
UserName = "Tua",
Password = "Tua",
Port =
};
using (var connection = factory.CreateConnection())
{
using (var channel = connection.CreateModel())
{
channel.ExchangeDeclare
(
exchange: "Tua",
type: ExchangeType.Fanout
);
for (int m = ; m < ; m++)
{
string marks = string.Empty;
for (int n = ; n <= m; n++)
{
marks += ">";
}
string msg = "Mr.Tua" + marks + marks.Length + "s";
var body = Encoding.UTF8.GetBytes(msg);
channel.BasicPublish
(
exchange: "Tua",
routingKey: "",
basicProperties: null,
body: body
);
Console.WriteLine("Producer sent message: {0}", msg);
}
Console.ReadLine();
}
}
}
}
}
Producer
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System;
using System.Linq;
using System.Text;
using System.Threading; namespace Consumer
{
class Program
{
static void Main(string[] args)
{
var factory = new ConnectionFactory
{
HostName = "localhost"
};
using (var connection = factory.CreateConnection())
{
using (var channel = connection.CreateModel())
{
channel.ExchangeDeclare
(
exchange: "Tua",
type: ExchangeType.Fanout
);
string queueName = channel.QueueDeclare().QueueName;
channel.QueueBind
(
queue: queueName,
exchange: "Tua",
routingKey: ""
);
var consumer = new EventingBasicConsumer(channel);
consumer.Received += (sender, e) =>
{
var body = e.Body;
var msg = Encoding.UTF8.GetString(body);
int marks = msg.ToCharArray().Where(c => c.ToString() == ">").Count();
Console.WriteLine("Consumer received message: {0}", msg);
Thread.Sleep(marks * );
Console.WriteLine("OK");
};
channel.BasicConsume
(
queue: queueName,
noAck: true,
consumer: consumer
);
Console.ReadLine();
}
}
}
}
}
Consumer
RabbitMQ --- Publish/Subscribe(发布/订阅)的更多相关文章
- php redis pub/sub(Publish/Subscribe,发布/订阅的信息系统)之基本使用
一.场景介绍 最近的一个项目需要用到发布/订阅的信息系统,以做到最新实时消息的通知.经查找后发现了redis pub/sub(发布/订阅的信息系统)可以满足我的开发需求,而且学习成本和使用成本也比较低 ...
- 译: 3. RabbitMQ Spring AMQP 之 Publish/Subscribe 发布和订阅
在第一篇教程中,我们展示了如何使用start.spring.io来利用Spring Initializr创建一个具有RabbitMQ starter dependency的项目来创建spring-am ...
- Part1.2 、RabbitMQ -- Publish/Subscribe 【发布和订阅】
python 目录 (一).交换 (Exchanges) -- 1.1 武sir 经典 Exchanges 案例展示. (二).临时队列( Temporary queues ) (三).绑定(Bind ...
- 【python】-- RabbitMQ Publish\Subscribe(消息发布\订阅)
RabbitMQ RabbitMQ Publish\Subscribe(消息发布\订阅) 1对1的消息发送和接收,即消息只能发送到指定的queue里,但这样使用有些局限性,有些时候你想让你的消息被所有 ...
- RabbitMQ入门:发布/订阅(Publish/Subscribe)
在前面的两篇博客中 RabbitMQ入门:Hello RabbitMQ 代码实例 RabbitMQ入门:工作队列(Work Queue) 遇到的实例都是一个消息只发送给一个消费者(工作者),他们的消息 ...
- RabbitMQ入门(3)——发布/订阅(Publish/Subscribe)
在上一篇RabbitMQ入门(2)--工作队列中,有一个默认的前提:每个任务都只发送到一个工作人员.这一篇将介绍发送一个消息到多个消费者.这种模式称为发布/订阅(Publish/Subscribe). ...
- RabbitMQ入门教程——发布/订阅
什么是发布订阅 发布订阅是一种设计模式定义了一对多的依赖关系,让多个订阅者对象同时监听某一个主题对象.这个主题对象在自身状态变化时,会通知所有的订阅者对象,使他们能够自动更新自己的状态. 为了描述这种 ...
- rabbitmq消息队列——"发布订阅"
三."发布订阅" 上一节的练习中我们创建了一个工作队列.队列中的每条消息都会被发送至一个工作进程.这节,我们将做些完全不同的事情--我们将发送单个消息发送至多个消费者.这种模式就是 ...
- RabbitMQ/JAVA (发布/订阅模式)
发布/订阅模式即生产者将消息发送给多个消费者. 下面介绍几个在发布/订阅模式中的关键概念-- 1. Exchanges (转发器) 可能原来我们都是基于一个队列发送和接收消息.现在介绍一下完整的消息传 ...
随机推荐
- WPF:动态显示或隐藏Listview的某一列
这几天做项目,需要做个listview满足能够动态显示或隐藏某些列,由于自己是菜鸟水平,查了两天资料也没有想出解决办法.就在我山穷水尽的时候看到了Mgen的一篇博客,给了我很大启发,所以我也决定把自己 ...
- 基于Dapper的分页实现,支持筛选,排序,结果集总数,非存储过程
简介 之前事先搜索了下博客园上关于Dapper分页的实现,有是有,但要么是基于存储过程,要么支持分页,而不支持排序,或者搜索条件不是那么容易维护. 代码 首先先上代码: https://github. ...
- Linux配置虚拟地址
立即生效: [root@server ~]$ 192.168.1.101 broadcast 192.168.1.255 netmask 255.255.255.0 up [root@server ~ ...
- maven Spring+Spring MVC+Mybatis+mysql轻量级Java web开发环境搭建
之前一直在做的一个GIS系统项目,采用了jsp+servlet框架,数据传输框架采用了apache的thrift框架,短时多传的风格还不错,但是较其他的java web项目显得有点太臃肿了,现在给大家 ...
- bzoj1041题解
求一个给定的圆(x^2+y^2=r^2),在圆周上有多少个点的坐标是整数.r<=2000 000 000 这道题刚看时,就明白暴力不能解决一切.要是r^2<=20亿,还可以sqrt循环, ...
- .NET 跨平台界面框架和为什么你首先要考虑再三
原文地址 现在用 C# 来开发跨平台应用已经有很成熟的方案,即共用非界面代码,而每个操作系统搭配特定的用户界面代码.这个方案的好处是可以直接使用操作系统原生的控件和第三方控件,还能够和操作系统 ...
- java多线程系列(二)
对象变量的并发访问 前言:本系列将从零开始讲解java多线程相关的技术,内容参考于<java多线程核心技术>与<java并发编程实战>等相关资料,希望站在巨人的肩膀上,再通过我 ...
- Vue2.0 生产环境部署
简要:继上次搭建vue环境后,开始着手vue的学习;为此向大家分享从开发环境部署到生产环境(线上)中遇到的问题和解决办法,希望能够跟各位VUE大神学习探索,如果有不对或者好的建议告知下:*~*! 一. ...
- LoadRunner接口测试Error -27225报错解决
今天依照规范写了一个接口测试脚本,再执行的时候报Error -27225,核对了接口字段和字段值没发现错误,百度搜Error -27225错误没有相关解释.这个问题经过溯源找到了问题的所在,为了互帮互 ...
- 玩玩微信公众号Java版之准备
微信自2013年流行起来,现在的发展已经超过了我们的想象,那么对应的公众平台,小程序等都是让人眼前一亮的东西,这里来学习一下微信工作号的对接,实现为Java,希望大家一起学习! 这里大概描述一下所 ...