C#/.Net集成RabbitMQ
RabbitMQ简介
消息 (Message) 是指在应用间传送的数据。消息可以非常简单,比如只包含文本字符串、 JSON 等,也可以很复杂,比如内嵌对象。
消息队列中间件 (Message Queue Middleware,简称为 MQ) 是指利用高效可靠的消息传递机制进行与平台无关的数据交流,并基于数据通信来进行分布式系统的集成。通过提供消息传递和消息排队模型,它可以在分布式环境下扩展进程间的通信。
消息队列中间件,也可以称为消息队列或者消息中间件。它一般有两种传递模式:点对点 (P2P, Point-to-Point) 模式和发布/订阅 (Pub/Sub) 模式。点对点模式是基于队列的,消息生产者发送消息到队列,消息消费者从队列中接收消息,队列的存在使得消息的异步传输成为可能。 发布订阅模式定义了如何向一个内容节点发布和订阅消息,这个内容节点称为主题 (topic),主题可以认为是消息传递的中介,消息发布者将消息发布到某个主题,而消息订阅者则从主题中订阅消息。主题使得消息的订阅者与消息的发布者互相保持独立,不需要进行接触即可保证消息的传递,发布/订阅模式在消息的一对多广播时采用 。
RabbitMQ是实现了高级消息队列协议(AMQP)的开源消息代理软件(亦称面向消息的中间件)。RabbitMQ服务器是用Erlang语言编写的,而集群和故障转移是构建在开放电信平台框架上的。所有主要的编程语言均有与代理接口通讯的客户端库。
关于RabbitMQ的原理及详细介绍百度上很多,这里就不做复制粘贴了。
生产者和消费者
在使用RabitMQ之前,先对几个概念做一下说明:
生产者(Producer):
生产者就是投递消息的一方。生产者创建消息,然后发布到 RabbitMQ 中。消息一般可以包含2个部分:消息体和标签 (Label)。消息体也可以称之为 payload,在实际应用中,消息体一般是一个带有业务逻辑结构的数据,比如一个JSON字符串。当然可以进一步对这个消息体进行序列化操作。消息的标签用来表述这条消息 ,比如一个交换器的名称和一个路由键。生产者把消息交由RabbitMQ,RabbitMQ之后会根据标签把消息发送给感兴趣的消费者 (Consumer)。
消息中间件的服务节点(Broker)
对于RabbitMQ来说,一个RabbitMQ Broker可以简单地看作一个RabbitMQ服务节点 ,或者RabbitMQ服务实例 。大多数情况下也可以将一个RabbitMQ Broker看作一台RabbitMQ服务器。
首先生产者将业务方数据进行可能的包装, 之后封装成消息, 发送 (AMQP 协议里这个动 作对应的命令为 Basic . Publish) 到 Broker 中 。 消费者订阅并接收消息 (AMQP 协议里这个动作对应的命令为 Basic.Consurne 或者 Basic. Get),经过可能的解包处理得到原始的数据, 之后再进行业务处理逻辑。这个业务处理逻辑并不一定需要和接收消息的逻辑使用同一个线程。 消费者进程可以使用一个线程去接收消息,存入到内存中。业务处理逻辑使用另一个线程从内存中读取数据,这样可以将应用进一步解稿,提高整个应用的处理效率。
队列(Queue)
队列,是RabbitMQ的内部对象,用于存储消息。RabbitMQ中消息都只能存储在队列中,RabbitMQ的生产者生产消息井最终技递到队列中,消费者可以从队列中获取消息并消费。多个消费者可以订阅同一个队列,这时队列中的消息会被平均分摊(Round-Robin,即轮询) 给多个消费者进行处理,而不是每个消费者都收到所有的消息井处理。
消费者(Consumer)
消费者,就是接收消息的一方。消费者连接到RabbitMQ服务器,并订阅到队列上。当消费者消费一条消息时,只是消费消息的消息体 (payload)。在消息路由的过程中,消息的标签会丢弃,存入到队列中的消息只 有消息体,消费者也只会消费到消体,也就不知道消息的生产者是谁,当然消费者也不需要知道。
项目中集成MQ
首先先安装好RabbitMQ,可以参考我之前写的教程 https://blog.csdn.net/yindi0712/article/details/107544076
1.这里我创建了一个Mvc项目作为生产者端,一个控制台作为消费者端
2.两个项目分别引用RabbitMQ.Client.dll,可以在官网下载:
下载地址:http://www.rabbitmq.com/releases/rabbitmq-dotnet-client/
也可以直接从Nuget中安装,二者效果是一样的
我这边选择用Nuget安装。
3.简单集成,实现消息生产和消费
生产者端
我这边创建了个简单的mvc项目,引用RabbitMQ.Client.dll,在HomeController创建一个名为Send的Action
public ActionResult Send(SendModel model)
{
//实例化一个连接工厂和其配置为使用所需的主机,虚拟主机和证书(证书)
ConnectionFactory factory = new ConnectionFactory();
factory.HostName = model.Url;//RabbitMQ主机服务地址
factory.UserName = model.UserName;//用户名
factory.Password = model.Password;//密码
//创建一个AMQP 0-9-1连接
using (IConnection connection = factory.CreateConnection())
{
//创建一个AMQP 0-9-1频道,该对象提供了大部分 的操作(方法)协议。
using (IModel channel = connection.CreateModel())
{
channel.QueueDeclare(model.Queue, false, false, false, null);//创建一个名称消息队列
string message = model.Content; //传递的消息内容
var body = Encoding.UTF8.GetBytes(message);
channel.BasicPublish("", model.Queue, null, body); //开始传递
}
}
return RedirectToAction("index");
}
消费者端
我这里创建了一个控制台应用,同样引用RabbitMQ.Client.dll,消费的逻辑直接写在Main方法里了
static void Main(string[] args)
{
//实例化一个连接工厂和其配置为使用所需的主机,虚拟主机和证书(证书)
ConnectionFactory factory = new ConnectionFactory();
factory.HostName = "127.0.0.1";//RabbitMQ主机服务地址
factory.UserName = "test";//用户名
factory.Password = "testpwd";//密码
//创建一个AMQP 0-9-1连接
using (IConnection connection = factory.CreateConnection())
{
//创建一个AMQP 0-9-1频道,该对象提供了大部分 的操作(方法)协议。
using (IModel channel = connection.CreateModel())
{
channel.QueueDeclare("getMessage", false, false, false, null);//声明一个名称消息队列
EventingBasicConsumer consumer = new EventingBasicConsumer(channel);//创建一个消费者实现c#事件处理程序实例
channel.BasicConsume("getMessage", false, consumer);//开始消费
//消息到达消费者时触发的事件
consumer.Received += (model, ea) =>
{
var body = ea.Body;
var message = Encoding.UTF8.GetString(body.ToArray());
Console.WriteLine("已接收: {0}", message);
};
Console.ReadLine();
}
}
}
总结:
1.首先不管是消费者还是生产者都要先创建一个连接工厂ConnectionFactory配置连接的基本信息;
2.通过ConnectionFactory.CreateConnection创建一个IConnection对象表示创建一个AMQP 0-9-1连接;
3.IConnection.CreateModel创建一个AMQP 0-9-1频道,该对象提供了大部分 的操作(方法)协议;
4.使用IModel.QueueDeclare声明一个消息队列,生产者和消费者的队列名称要一致;
5.生产者端:使用IModel.BasicPublish发送消息到消息队列;
6.消费者端:创建一个消费者事件对象EventingBasicConsumer;使用IModel.BasicConsume将该消费者启动,在消息接收触发事件EventingBasicConsumer.Received做后续操作。
至此一个简单的消费者和生产者端就搭建好了,下面我们运行起来看一下效果:
上面是我本地的配置信息,下面我创建一个getMessage队列并发送一条123的消息。
我们直接进管理界面看吧,就不敲命令了,如果本地装了管理插件直接访问http://127.0.0.1:15672/,我们先进到Queues,我们可以看到刚刚创建的getMessage队列
然后进入到队列内部,去点一下GetMessages按钮:
我们可以看到刚才发送的123已经在队列中了,现在我们运行消费者端
我们可以看到这个消息已经输出出来了,这时候再去点击GetMessages,这时候就会提示Queue is empty,表示该消息已经消费了。可以把两个项目同时运行,多发几条消息基本上是事实的。
————————————————————————————————————————————————————
今天先写到这,后面再说说响应机制集群幂等性啥的
C#/.Net集成RabbitMQ的更多相关文章
- rabbitMQ第五篇:Spring集成RabbitMQ
前面几篇讲解了如何使用rabbitMq,这一篇主要讲解spring集成rabbitmq. 首先引入配置文件org.springframework.amqp,如下 <dependency> ...
- RabbitMQ第四篇:Spring集成RabbitMQ
前面几篇讲解了如何使用rabbitMq,这一篇主要讲解spring集成rabbitmq. 首先引入配置文件org.springframework.amqp,如下 <dependency> ...
- springboot集成rabbitmq(实战)
RabbitMQ简介RabbitMQ使用Erlang语言开发的开源消息队列系统,基于AMQP协议来实现(AMQP的主要特征是面向消息.队列.路由.可靠性.安全).支持多种客户端,如:Python.Ru ...
- SpringBoot集成rabbitmq(二)
前言 在使用rabbitmq时,我们可以通过消息持久化来解决服务器因异常崩溃而造成的消息丢失.除此之外,我们还会遇到一个问题,当消息生产者发消息发送出去后,消息到底有没有正确到达服务器呢?如果不进行特 ...
- SpringBoot集成rabbitmq(一)
前言 Rabbitmq是一个开源的消息代理软件,是AMQP协议的实现.核心作用就是创建消息队列,异步发送和接收消息.通常用来在高并发中处理削峰填谷.延迟处理.解耦系统之间的强耦合.处理秒杀订单. 入 ...
- Spring Boot系列——7步集成RabbitMQ
RabbitMQ是一种我们经常使用的消息中间件,通过RabbitMQ可以帮助我们实现异步.削峰的目的. 今天这篇,我们来看看Spring Boot是如何集成RabbitMQ,发送消息和消费消息的.同时 ...
- SpringBoot集成RabbitMQ消息队列搭建与ACK消息确认入门
1.RabbitMQ介绍 RabbitMQ是实现AMQP(高级消息队列协议)的消息中间件的一种,最初起源于金融系统,用于在分布式系统中存储转发消息,在易用性.扩展性.高可用性等方面表现不俗.Rabbi ...
- RabbitMQ(3) Spring boot集成RabbitMQ
springboot集成RabbitMQ非常简单,如果只是简单的使用配置非常少,springboot提供了spring-boot-starter-amqp项目对消息各种支持. 资源代码:练习用的代码. ...
- 集成RabbitMQ做秒杀
由于秒杀的并发量太大,所以仅仅使用缓存是不够的,还需要用到RabbitMQ. 这里推荐一款用于分库分表的中间件:mycat 解决超卖的问题(看第五章节): 秒杀接口优化: 实操: 然后把下载好的文件上 ...
- Spring boot集成RabbitMQ(山东数漫江湖)
RabbitMQ简介 RabbitMQ是一个在AMQP基础上完整的,可复用的企业消息系统 MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法.应用程序通过读写出 ...
随机推荐
- 爬虫04 /asyncio、selenium规避检测、动作链、无头浏览器
爬虫04 /asyncio.selenium规避检测.动作链.无头浏览器 目录 爬虫04 /asyncio.selenium规避检测.动作链.无头浏览器 1. 协程asyncio 2. aiohttp ...
- gvim使用总结
我的gvim配置 set nocompatible " 关闭vi兼容 " 显示相关 set go= set number set cursorline set nowrap set ...
- Python 为什么只需一条语句“a,b=b,a”,就能直接交换两个变量?
从接触 Python 时起,我就觉得 Python 的元组解包(unpacking)挺有意思,非常简洁好用. 最显而易见的例子就是多重赋值,即在一条语句中同时给多个变量赋值: >>> ...
- SpringBoot代码生成器
Code-Generate 代码生成器 简介 一个基于原生Mysql & SpringBoot & Mybatis 的代码生成器,建表之后即可完全解放双手,适合: 规律性定制化开发 解 ...
- JVM系列之:String,数组和集合类的内存占用大小
目录 简介 数组 String ArrayList HashMap HashSet LinkedList treeMap 总结 简介 之前的文章中,我们使用JOL工具简单的分析过String,数组和集 ...
- java io流根据url读取图片
//获取图片大小 public void readFileSize(String url,HttpServletRequest request){ //根路径 File file = new File ...
- w10查看wifi密码
1.选择网络和Internet设置 右键单击网络连接图标,选择“打开网络和Internet设置”. 2.选择网络和共享中心
- 今天成功完成二维码扫描程序, 利用zxing
利用的网上参考文档是https://blog.csdn.net/gorky_19/article/details/78454030,里面介绍了如何修改build.gradle的dependency 和 ...
- Azure Load Balancer(一) 为我们的Web项目提供负载均衡
一,引言 上节,我们讲到使用 Azure Traffic Manager 为我们的 Demo 项目提供负载均衡,以及流量转发的功能.但是Azure 提供类似的功能的服务远远不止这一个,今天我们就来讲一 ...
- 在 Laravel 中通过自定义分页器分页方法实现伪静态分页链接以利于 SEO
我们知道,Laravel 自带的分页器方法包含 simplePaginate 和 paginate 方法,一个返回不带页码的分页链接,另一个返回带页码的分页链接,但是这两种分页链接页码都是以带问号的动 ...