RabbitMQ可以被比作一个邮局,当你向邮局寄一封信时,邮局会保证将这封信送达你写的收件人,而RabbitMQ与邮局最主要的区别是,RabbitMQ并不真的处理信件,它处理的是二进制的数据块,它除了接收“信件”,他还要负责处理数据(比如保存数据)、转发数据(实际上送信是邮递员的职责)等。

  在RabbitMQ中有以下几个概念:

  • 生产者

  一个生产者仅仅负责向RabbitMQ中发送消息,除此之外它不会完成其他工作。

  • 队列

  队列由RabbitMQ自身提供,它的作用就像是邮箱和邮局的关系一样。虽然看似RabbitMQ和你的应用直接通信,但是实际上消息是被存储到队列中的,实际上,队列就是一个消息缓冲区,受宿主环境内存和磁盘空间的限制。多个生产者可以将消息发送到一个队列,而多个消费者可以从一个队列中接收消息。

  • 消费者

  一个消费者仅仅负责接收来自生产者的消息。

  这里需要注意以下两点:

  1. 生产者、消费者和RabbitMQ不一定必须在相同的宿主机上,在实际的生产环境中,它们常常处于不同的宿主机;
  2. 某个应用既可以同时是一个生产者和消费者。

  我们需要建立两个.net core项目,分别是发布端、接收端,它们由消息队列进行连接,消息队列会保存消息,直到消息被发送给接收端,如图所示。

  下面开始创建项目: 

  创建项目后,两个项目均需安装RabbitMQ.Client的Nuget包,并restore。

  在正式开始编写发送端代码之前,我们需要安装RabbitMQ,这里我在Docker上安装RabbitMQ,所用系统为CentOS7。
  首先创新新的文件夹目录/docker/rabbitmq/data,用作RabbitMQ容器的数据卷挂载。

  然后运行下面的语句,如果本地没有镜像,Docker会自动去Dockerhub上拉取镜像:

docker run -d -p 5672:5672 -p 15672:15672 --name rabbitmq --volume /rabbitmq/data:/var/lib/rabbitmq rabbitmq:management

  镜像下载完毕后可以看到容器已经运行,其中,15671用于外网访问,5672用于内网连接。

  访问http://ip:15671,不出意外你可以进入到RabbitMQ的可视化管理界面。

  • 生产者端

  下面可以开始编写生产者端的代码,如下所示。

using System;
using System.Text;
using RabbitMQ.Client; namespace Send
{
class Program
{
static void Main(string[] args)
{
var factory = new ConnectionFactory() { HostName = "148.70.210.208" };
//连接RabbitMQ
using (var connection = factory.CreateConnection())
{
//创建一个信道
using (var channel = connection.CreateModel())
{
//声明一个Hello队列,信道就与Hello队列连接起来了
channel.QueueDeclare(queue: "hello",
durable: false,
exclusive: false,
autoDelete: false,
arguments: null); string message = "Hello World!";
//消息体
var body = Encoding.UTF8.GetBytes(message); //通过信道,将消息发送到队列
//需要指明队列的名称,才能转发到特定队列
channel.BasicPublish(exchange: "",
routingKey: "hello",
basicProperties: null,
body: body); Console.WriteLine(" [x] Sent [0]", message);
} Console.WriteLine("Press [enter] to exit.");
Console.ReadLine();
}
}
}
}

  程序首先通过Socket与RabbitMQ进行了连接,连接成功后,创建了一个信道,并通过这个信道声明了一个名叫"hello"的队列,这样,队列就和这个信道绑定起来,在发送数据时,只需要在routingKey中指明所用的队列名,消息就会通过direct exchange的模式被发送到指明名称的队列中,这就好像你在网上买了商品,然后你告诉卖家,一定要发某个快递一样,这样,你的商品就会通过这个快递公司邮寄给你。

  direct exchange模式如图所示。

  整个流程可以如下进行概括,首先建立发布端和RabbitMQ进行Socket连接,并且声明Socket连接中的信道,通过这个信道声明特定名称的队列,这样,数据就可以通过这个信道发送到RabbitMQ的队列中,等待被转发到消费端,这与官网给出的流程图如出一辙。

  

  

  • 消费者端 

  下面我们就可以开始编写消费端的程序,对于消费者端来说,它一直在进行监听,我们需要一直运行我们的监听程序,一旦收到消息,就把消息通过控制台进行打印。
  打开我们的Recieve项目,代码如下所示。

using System;
using System.Text;
using RabbitMQ.Client;
using RabbitMQ.Client.Events; namespace Receive
{
class Program
{
static void Main(string[] args)
{
var factory = new ConnectionFactory() { HostName = "your ip address" };
using (var connection = factory.CreateConnection())
{
using (var channel = connection.CreateModel())
{
channel.QueueDeclare(queue: "hello",
durable: false,
exclusive: false,
autoDelete: false,
arguments: null); var consumer = new EventingBasicConsumer(channel); consumer.Received += (model, ea) =>
{
var body = ea.Body;
var message = Encoding.UTF8.GetString(body);
Console.WriteLine($"Received message:{message}");
}; channel.BasicConsume(queue: "hello",
autoAck: true,
consumer: consumer); Console.WriteLine("Press [enter] to exit");
Console.ReadLine();
}
}
}
}
}

  一开始的代码与发送端一致,建立连接、创建信道、声明队列,需要注意这里声明的队列名需要与发送端绑定的队列名一致。这里之所以重新声明队列,是为了保证当接收端程序比发送端先启动时,队列依然是存在的,但是需要保证名称一样。

  以上准备工作完成后,接收端可以开始异步的接收队列中的数据了。我们使用EventBasicConsumer.Received事件来绑定接收完成的回调函数。即:当消费端成功从"hello"队列中接收到数据后,就会调用这个匿名的lambda表达式,从消息体中获取数据,将数据转码成字符串格式并且打印到控制台中,至此,一条消息的处理就完毕了。
  需要注意,在消费端收到信息后,需要给客户端确认,即返回autoAck,如果没有返回,客户端会默认消费者没有收到,消息会存储在队列中,直到被消费。这里设置autoAck:true,则表示消费者一旦收到消息,则立刻自动的向客户端回应,这样,消息就会从队列中删除。

  • 测试代码

  运行代码可以看到,无论先运行消费端还是生产者端的代码,消费端都能收到消息:

  如果先运行生产者端程序,消息会存储在消息队列中,当运行消费者端程序后,保存在消息队列中的消息将会被消费,进而从队列中删除。
  例如,我们先不运行消费者端程序,只运行生产者端,这是我们刷新RabbitMQ的可视化界面。

  可以看到有一条消息处于Ready状态,但是还未被消费,所以被存储,我们关闭生产者端程序,再次运行,可以看到队列中未被消费的消息变为两条。

  这时,我们运行消费者端程序,运行成功后可以看到,消费者端一次收到了两条消息,并且队列中的消息被清除。

  

  由此可见,对于RabbitMQ的消息队列,生产者和消费者端是完全分离的。
  下一讲我们将继续探索RabbitMQ的工作队列。

  

.NET Core RabbitMQ探索(1)的更多相关文章

  1. .NET Core RabbitMQ探索(2)——RabbitMQ的Exchange

    实际上,RabbitMQ的生产者并不会直接把消息发送给队列,甚至生产者都不知道消息是否会被发送给一个队列.对于生产者而言,它们只能把消息发送到Exchange,一个Exchange所完成的工作相当简单 ...

  2. IdentityServer4 + SignalR Core +RabbitMQ 构建web即时通讯(三)

    IdentityServer4 + SignalR Core +RabbitMQ 构建web即时通讯(三) 后台服务用户与认证 新建一个空的.net core web项目Demo.Chat,端口配置为 ...

  3. IdentityServer4 + SignalR Core +RabbitMQ 构建web即时通讯(二)

    IdentityServer4 + SignalR Core +RabbitMQ 构建web即时通讯(二) IdentityServer4 用户中心生成数据库 上文已经创建了所有的数据库上下文迁移代码 ...

  4. IdentityServer4 + SignalR Core +RabbitMQ 构建web即时通讯(一)

    IdentityServer4 + SignalR Core +RabbitMQ 构建web即时通讯 前言 .net core 2.1已经正式发布了,signalr core1.0随之发布,是时候写个 ...

  5. HMS Core积极探索基于硬件耳返的功能,帮助唱吧整体唱歌延迟率降低60%

    唱吧的使命是让唱歌更简单.让生活更美好,其布局的K歌业务专注于让曲库更全.音质更好,开创了同框合唱.弹唱等有意思的游戏类K歌玩法.为了让用户拥有更加沉浸的娱乐体验,唱吧与HMS Core积极探索基于硬 ...

  6. .net core RabbitMQ 消息队列

    上篇我们说到erlang的安装,现在有了基础前提,就可以继续安装RabbitMQ了! 这里我选用的RabbitMQ版本是: PS:这个RabbitMQ版本是要对应前面erlang版本,所以前面我们安装 ...

  7. ASP.NET Core框架探索(一)

    今天我们来结合源码来探究一下ASP.NET CORE Web框架的运行原理. 可以先整体看一下下面这张基于源码分析过程的一个总结大纲,包含各环节完成的关键步骤: 下面我们将一起来结合源码探索启动一个A ...

  8. ASP.NET Core框架探索之Authentication

    今天我们来探索一下ASP.NET Core中关于权限认证,所谓权限认证,就是通过某些方式获取到用户的信息. 需要开启权限认证,我们首先需要在容器中注入认证服务,使用services.AddAuthen ...

  9. ASP.NET Core框架探索之Authorization

    今天我们一起来探索一下ASP.NET Core框架中的Authorization.我们知道请求进入管道处理流程先会使用Authentication进行用户认证,然后使用Authorization进行用 ...

随机推荐

  1. Python3---爬虫Post传参

    前言 Python3 Post 传参主要用到的是urllib.request.urlopen(url,data)参数当中data.data参数主要是设置post的传参. 修改时间:20191218 天 ...

  2. ArchLinux 2019.11.01安装流程--安装基本系统

    安装前的一些话 本文是参考官方文档ArchLinux的Installation guide(简体中文)加实际操作编写的. 有啥都好说,转载时请注明作者,这是基本素质,也是法律要求 安装是在虚拟机上进行 ...

  3. 双十一DIY装机记

    一.装机背景   最近发现古董笔记本太卡了,用了近6年,尽管自己不打游戏,但是业余时间写写代码,同时开两个编辑器,打开个大一点的软件都卡的不行,据说更换固态硬盘可以提高速度,于是乎,京东买了一个500 ...

  4. ES2019新特性的学习

    前言 前端技术更新的实在是太快了,各种框架百花齐放,随着NodeJs不断的兴起,各种构建工具也是层出不穷,这不,前两周尤雨溪开源了Vue.js3.0源码之后,很多大佬早已把源码剖析皮都不剩了:昨天No ...

  5. Dynamics 365 Customer Engagement中使用JavaScript和C#调用操作Action示例

    微软动态CRM专家罗勇 ,回复334或者20190509可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me! Action (操作)是流程的一种,可以在工作流中调用,可以使用 ...

  6. arcgis api for javascript 学习(二) 发布并调用地图切片

    文章将从发布切片地图到调用切片地图整个过程都展示出来. (一).切片地图的发布 1.还是前面的arcgis展示的地图 2.与发布动态地图前面的步骤是一样的 打开分享后,如图 3.一切就绪后,到达缓存的 ...

  7. 安卓开发笔记(三十二):banner轮播图的实现

    一.activity.xml 我这里主要爬取的爱奇艺首页的图片进行轮播,应用了两个github上的开源库,一个banner的库,一个加载网络图片的库,用开源库能够极大地节省我们编写代码的时间. < ...

  8. 微服务:Eureka+Zuul+Ribbon+Feign+Hystrix构建微服务架构

    原文地址:http://blog.csdn.net/qq_18675693/article/details/53282031 本案例将打架一个微服务框架,参考来源官方参考文档 微服务:是什么?网上有一 ...

  9. JS之for循环面试题

    今天同事问了道问题 ,b=; ,b<;++a,++b){ g=a+b } console.log(g) 问输出结果为多少??? 答案:12 这里要知道for循环的条件不管写多少个,必须都满足才可 ...

  10. 扎西平措 201571030332 《面向对象程序设计 (JAVA)》第二周 学习总结

    面向对象程序设计 (JAVA)>第二周 学习总结 项目 内容 这个作业属于哪个课程 <任课教师博客主页链接>https://www.cnblogs.com/nwnu-daizh/ 这 ...