一、发布/订阅(Publish/Subscribe)模式

发布订阅是我们经常会用到的一种模式,生产者生产消息后,所有订阅者都可以收到。RabbitMQ的发布/订阅模型图如下:



1、该模式下生产者并不是直接操作队列,而是将数据发送给交换机,由交换机将数据发送给与之绑定的队列;

2、该模式必须声明交换机,并且设置模式: channel.ExchangeDeclare(EXCHANGE_NAME, type: ExchangeType.Fanout);  

fanout指分发模式(将每一条消息都发送到与交换机绑定的队)。

3、队列必须绑定交换机:channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "");

二、发布消息

消息生产者向交换机(exchange)发送消息,代码如下:

   // 定义交换机名称
static string EXCHANGE_NAME = "ps_exchange_fanout";
public static void PublishMessage()
{
try
{
var conn = RabbitMQHelper.GetConnection();
var channel = conn.CreateModel();
// 定义exchange
channel.ExchangeDeclare(EXCHANGE_NAME, type: ExchangeType.Fanout);
string msg = "hello ps!";
var body = Encoding.UTF8.GetBytes(msg);
channel.BasicPublish(EXCHANGE_NAME, "", null, body);
Console.WriteLine("send msg:" + msg);
channel.Close();
conn.Close();
}
catch (Exception ex)
{
throw ex;
}
}

消息发送成功,截图如下:

三、订阅消息

在这里需要两个消费者,消息发送后,所有的订阅者都可以收到消息;

3.1 消费者1

和轮询分发以及公平分发不同的是,消费者需要将队列绑定到交换机,来订阅消息;实现代码如下:

        static string EXCHANGE_NAME = "ps_exchange_fanout";
static string QUEUE_NAME = "ps_queue_sub1";
/// <summary>
/// 订阅消费者1
/// </summary>
static void SubscribeConsumer1()
{
var conn = RabbitMQHelper.GetConnection();
var channel = conn.CreateModel();
// 定义exchange
channel.ExchangeDeclare(EXCHANGE_NAME, type: ExchangeType.Fanout);
// 绑定queue
channel.QueueDeclare(queue: QUEUE_NAME);
channel.QueueBind(QUEUE_NAME, EXCHANGE_NAME, "");
// 定义Consumer
var consumer = new EventingBasicConsumer(channel);
consumer.Received += (model,ea) =>
{
var body = ea.Body;
var message = Encoding.UTF8.GetString(body.ToArray());
Console.WriteLine($"SubscribeConsumer1 收到消息: {message},时间:{DateTime.Now}");
};
//启动消费者 设置为手动应答消息
channel.BasicConsume(queue: QUEUE_NAME, autoAck: true, consumer: consumer);
Console.WriteLine("Subscribe Consumer1 消费者已启动");
Console.ReadKey();
channel.Dispose();
conn.Close();
}

3.2 消费者2

消费者2的代码和1的基本相同,大家可以将1的修改一下,就可以使用,在此就不重复贴出了;

3.3 接收消息结果

消费者1接收消息截图:



消费者2接收消息截图:



通过上图,我们可以看到,发布者发布消息后,订阅者1、2均受到了相同的消息,至此功能已经完成;

四、小结

4.1 订阅者代码的主要流程

根据消费者的代码,我们可以提炼流程如下

(1)创建连接

(2)声明exchange

(3)绑定队列到exchange

(4)声明消费者

(5)绑定消费者到channel,监听处理消息

(6)关闭连接

4.2 订阅成功后,我们打开mq的管理地址可以看到,有两个queue绑定到exchange上了:



注意:如果我们的exchange没有消费者订阅,发布的消息将不会被保存到任何队列,直接丢失了;

参考链接:https://www.rabbitmq.com/tutorials/tutorial-three-dotnet.html

RabbitMQ的发布订阅模式(Publish/Subscribe)的更多相关文章

  1. 【译】RabbitMQ:发布-订阅(Publish/Subscribe)

    在前一篇教程中,我们创建了一个工作队列,我们假设在工作队列后的每一个任务都只被调度给一个消费者.在这一部分,我们将做一些完全不一样的事情,调度同一条消息给多个消费者,也就是有名的“发布-订阅”模式.为 ...

  2. 四.RabbitMQ之发布/订阅(Publish/Subscribe)

    一.基础知识点 在上述章节中,我们理解的RabbitMQ是基于如下这种模式运作的. 而事实上,这只是我们简单化了的模型的结果,真正的模型应该是这样的. P:Producer 生产者,生产消息,把它放进 ...

  3. RabbitMQ系列教程之三:发布/订阅(Publish/Subscribe)(转载)

    RabbitMQ系列教程之三:发布/订阅(Publish/Subscribe) (本教程是使用Net客户端,也就是针对微软技术平台的) 在前一个教程中,我们创建了一个工作队列.工作队列背后的假设是每个 ...

  4. Mina、Netty、Twisted一起学(七):发布/订阅(Publish/Subscribe)

    消息传递有很多种方式,请求/响应(Request/Reply)是最常用的.在前面的博文的例子中,很多都是采用请求/响应的方式,当服务器接收到消息后,会立即write回写一条消息到客户端.HTTP协议也 ...

  5. RabbitMQ入门:发布/订阅(Publish/Subscribe)

    在前面的两篇博客中 RabbitMQ入门:Hello RabbitMQ 代码实例 RabbitMQ入门:工作队列(Work Queue) 遇到的实例都是一个消息只发送给一个消费者(工作者),他们的消息 ...

  6. RabbitMQ系列教程之三:发布/订阅(Publish/Subscribe)

    (本教程是使用Net客户端,也就是针对微软技术平台的)   在前一个教程中,我们创建了一个工作队列.工作队列背后的假设是每个任务会被交付给一个[工人].在这一部分我们将做一些完全不同的事情--我们将向 ...

  7. RabbitMQ 之 订阅模式 Publish/Subscribe

    模型图 我们之前学习的都是一个消息只能被一个消费者消费,那么如果我想发一个消息 能被多个消费者消费,这时候怎么办? 这时候我们就得用到了消息中的发布订阅模型 在前面的教程中,我们创建了一个工作队列,都 ...

  8. RabbitMQ入门-发布订阅模式

    兔子的Publish/Subscribe是这样的: 有个生产者P,X代表交换机,交换机绑定队列,消费者从队列中取得消息.每次有消息,先发到交换机中,然后由交换机负责发送到它已知的队列中. 生产者代码: ...

  9. 观察者(Observer)模式又名发布-订阅(Publish/Subscribe)模式、模型-视图(View)模式、源-收听者(Listener)模式或从属者模式

    观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己. 抽象主题(Subject):它把所有观察者对 ...

随机推荐

  1. JMeter分布式压测-常见问题之(Server failed to start: java.rmi.server.ExportException: Listen failed on port: 0; nested exception )

    问题描述: 在Linux环境启动jmeter-server时抛出了如下异常: 问题描述: 1.可能监听的端口被占用,修改端口号2.Server相关的rmi配置需要调整 解决方案: 在目录/apache ...

  2. 前端面试的那些事儿(1)~JavaScript 原始数据类型

    前言 自我总结面试常问的一些细节,方便不断回顾与补充.第一次发表文章,如有问题或不足之处望及时指出. JavaScript 原始数据类型 1.1 基础数据类型 7大基础数据类型 boolean nul ...

  3. JDBC处理CLOB 和 BLOB大对象

    在数据库中: clob用于存储大量的文本数据 可以使用字符流操作 clob用于存储大量的二进制数据 可以使用字节流操作 以mysql为例 先准备一张表: CREATE TABLE `t_user2` ...

  4. 一款被大厂选用的 Hexo 博客主题

    首先这是一篇自吹自擂的文章,主题是由多位非前端程序员共同开发,目前经过一年半的迭代已经到达 v1.8.0 版本,并且获得大量认可,甚至某大厂员工已经选用作为内部博客,因此我决定写这篇文章向更多人安利它 ...

  5. 【Linux常见命令】route命令

    route - show / manipulate the IP routing table route命令用于显示和操作IP路由表. route命令用来显示并设置Linux内核中的网络路由表,rou ...

  6. UVA10599:Robots(II)(最长上升子序列)

    Your company provides robots that can be used to pick up litter from fields after sporting events an ...

  7. SSH 超时设置

    在阿里云买了一台乞丐版服务器,搭了一个博客,安装了java,mysql,redis等服务,把以前写的知乎爬虫部署上去,看看爬取效果.程序运行一段时间后,发现cmder上的日志不打了,我原以为爬虫挂了, ...

  8. React全家桶+AntD 共享单车后台管理系统开发

    第1章 课程导学对课程整体进行介绍,并且说明学习的必要性.第2章 React基础知识React基础知识以及生命周期的介绍,并使用React官方脚手架初始化基础项目,同时介绍了新一代打包工具Yarn.第 ...

  9. Spring Developer Tools 源码分析:三、重启自动配置'

    接上文 Spring Developer Tools 源码分析:二.类路径监控,接下来看看前面提到的这些类是如何配置,如何启动的. spring-boot-devtools 使用了 Spring Bo ...

  10. 解决 Retrofit 多 BaseUrl 及运行时动态改变 BaseUrl ?

    原文地址: juejin.im/post/597856- 解决Retrofit多BaseUrl及运行时动态改变BaseUrl(一) 解决Retrofit多BaseUrl及运行时动态改变BaseUrl( ...