抽一根烟的时间学会.NET Core 操作RabbitMQ
什么是RabbitMQ?
RabbitMQ是由erlang语言开发的一个基于AMQP(Advanced Message Queuing Protocol)协议的企业级消息队列中间件。可实现队列,订阅/发布,路由,通配符等工作模式。
为什么要使用RabbitMQ?
- 异步处理:比如发送邮件,发送短信等不需要等待处理结果的操作
- 应用解耦:比如下单成功后,通知仓库发货,不需要等待仓库回应,通过消息队列去通知仓库,降低应用间耦合程序,可并行开发两个功能模块
- 流量削锋:在抢购或者其他的活动页,服务处于爆发式请求状态,如果直连数据库,数据库容易被拖垮。抢购商品也容易出现库存超卖的情况。通过队列可有效解决该问题。
- 日志处理:在单机中,日志直接写入到文件目录中,但是在分布式应用中,日志需要有统一的处理机制,可通过消息队列统一由某个消费端做处理。
- 消息通信:如生产端和消费端可通过队列进行异步通信
如何安装RabbitMQ?
Windows端
安装erlang语言运行环境
https://erlang.org/download/otp_win64_23.2.exe
下载后直接下一步即可安装RabbitMQ
https://www.rabbitmq.com/install-windows.html#installer
直接点击安装下一步即可按章安装RabbitMQ的Web管理平台
RabbitMQ的管理平台是通过插件的形式使用,需要手动启用管理平台
在Windows下,RabbitMQ默认被安装到C:\Program Files\RabbitMQ Server\rabbitmq_server-3.8.14 下。
打开sbin ,在cmd或者powershell中执行
rabbitmq-plugins.bat enable rabbitmq_management
安装完成后,浏览器打开 http://localhost:15672/#/ 即可看到RabbitMQ的管理界面。输入默认账号密码 guest 成功登录。
Linux环境安装
- Ubuntu:https://www.rabbitmq.com/install-debian.html
- Centos:https://www.rabbitmq.com/install-rpm.html
RabbitMQ的基本概念了解一下?
生产者
发送消息的端
消费者
获取消息并处理的端
Connection
一个终端连接。每一个Connection都可以在RabbitMQ后台看到
Channel
Channel是建立在Connection上的一个虚拟通信管道。一般情况下,往消息队列中写入多条消息,为了不每条消息都建立一个TCP连接,所以RabbitMQ的做法是多条消息可以公用一个Connection,大大提高MQ的负载能力。
Exchange
Exchange是一个虚拟交换机。每一条消息都必须要通过交换机才能能进入对应的队列,可以理解为网络设备中的交换机,是一个意思。
Queue
Queue是一个存储消息的内部对象,所有的Rabbit MQ消息都存储在Queue中。生产者所生产的消息会存储在Queue中,消费者获取的消息也是从Queue中获取。
如何在.NET Core中使用RabbitMQ?
nuget安装
dotnet add package RabbitMQ.Client
创建生产者
const string QUEUENAME = "HELLO_MQ";
//创建连接对象工厂
var factory = new ConnectionFactory()
{
UserName = "guest",
Password = "guest",
HostName = "localhost",
Port = 5672, //RabbitMQ默认的端口
};
while (true)
{
using var conn = factory.CreateConnection();
var chanel = conn.CreateModel();
chanel.QueueDeclare(QUEUENAME, true, false, false);
Console.WriteLine("输入生产内容:");
var input = Console.ReadLine();
chanel.BasicPublish("", QUEUENAME, null, Encoding.Default.GetBytes("hello rabbitmq:" + input));
}
在循环中,输入一个值,按下enter,即可推送一条消息到队列。
也可以直接在RabbitMQ的管理后台查看
可以看到我们发送的消息已经被RabbitMQ存储在Queue中了。只等某个幸运的消费者前来消费。
创建消费者
const string QUEUENAME = "HELLO_MQ";
var factory = new ConnectionFactory()
{
UserName = "guest",
Password = "guest",
HostName = "localhost",
Port = 5672,
};
var conn = factory.CreateConnection();
var chanel = conn.CreateModel();
chanel.QueueDeclare(QUEUENAME, true, false, false);
EventingBasicConsumer consumer = new EventingBasicConsumer(chanel);
consumer.Received += (a, e) =>
{
Console.WriteLine($"{DateTime.Now.ToString()}接收到消息:" + Encoding.Default.GetString(e.Body.ToArray()));
chanel.BasicAck(e.DeliveryTag, true); //收到回复后,RabbitMQ会直接在队列中删除这条消息
};
chanel.BasicConsume(QUEUENAME, false, consumer);
Console.WriteLine("启动成功");
Console.ReadLine();
启动成功后,consumer的Received方法,会收到一条来自MQ的消息,
如果处理完成后,不调用chennel的BasicAck方法,那么这条消息依然会存在,下次有消费者出现,会再次推送给消费者。
简单的RabbitMQ Hello World到这里就算完成了。接下来就是稍微高级一点的应用
RabbitMQ的工作模式
Work Queue 工作队列模式
工作队列模式的意思就是一个生产者对应多个消费者。RabbitMQ会使用轮询去给每个消费者发送消息。
publish/subscribe
发布订阅模式是属于比较用多的一种。
发布订阅,是由交换机发布消息给多个队列。多个队列再对应多个消费者。
发布订阅模式对应的交换机类型的fanout。
消费者
A
const string QUEUENAME = "HELLO_MQ_B";
const string TESTEXCHANGE = "TESTEXCHANGE";
var factory = new ConnectionFactory()
{
UserName = "guest",
Password = "guest",
HostName = "localhost",
Port = 5672,
};
var conn = factory.CreateConnection();
var channel = conn.CreateModel();
//定义队列
channel.QueueDeclare(QUEUENAME, true, false, false);
//定义交换机
channel.ExchangeDeclare(TESTEXCHANGE, ExchangeType.Fanout, true, false);
//绑定队列到交换机
channel.QueueBind(QUEUENAME, TESTEXCHANGE, "");
var consumer = new EventingBasicConsumer(channel);
consumer.Received += (a, e) =>
{
Console.WriteLine($"{DateTime.Now.ToString()}接收到消息:" + Encoding.Default.GetString(e.Body.ToArray()));
channel.BasicAck(e.DeliveryTag, true); //收到回复后,RabbitMQ会直接在队列中删除这条消息
};
channel.BasicConsume(QUEUENAME, false, consumer);
Console.WriteLine("启动成功");
Console.ReadLine();
B
const string QUEUENAME = "HELLO_MQ";
const string TESTEXCHANGE = "TESTEXCHANGE";
var factory = new ConnectionFactory()
{
UserName = "guest",
Password = "guest",
HostName = "localhost",
Port = 5672,
};
var conn = factory.CreateConnection();
var channel = conn.CreateModel();
//定义队列
channel.QueueDeclare(QUEUENAME, true, false, false);
//定义交换机
channel.ExchangeDeclare(TESTEXCHANGE, ExchangeType.Fanout, true, false);
//绑定队列到交换机
channel.QueueBind(QUEUENAME, TESTEXCHANGE, "");
var consumer = new EventingBasicConsumer(channel);
consumer.Received += (a, e) =>
{
Console.WriteLine($"{DateTime.Now.ToString()}接收到消息:" + Encoding.Default.GetString(e.Body.ToArray()));
channel.BasicAck(e.DeliveryTag, true); //收到回复后,RabbitMQ会直接在队列中删除这条消息
};
channel.BasicConsume(QUEUENAME, false, consumer);
Console.WriteLine("启动成功");
Console.ReadLine();
生产者
const string QUEUENAME = "HELLO_MQ";
const string QUEUENAME_B = "HELLO_MQ_B";
const string TESTEXCHANGE = "TESTEXCHANGE";
//创建连接对象工厂
var factory = new ConnectionFactory()
{
UserName = "guest",
Password = "guest",
HostName = "localhost",
Port = 5672, //RabbitMQ默认的端口
};
using var conn = factory.CreateConnection();
while (true)
{
var channel = conn.CreateModel();
//定义交换机
channel.ExchangeDeclare(TESTEXCHANGE, ExchangeType.Fanout, true, false);
Console.WriteLine("输入生产内容:");
var input = Console.ReadLine();
channel.BasicPublish(TESTEXCHANGE,"", null, Encoding.Default.GetBytes("hello rabbitmq:" + input));
}
在生产者运行成功后,RabbitMQ后台会出现一个交换机,点击交换机会看到交换机下绑定了两个队列
从生产者发送消息到队列,两个消费者会同时收到消息
routing模式
routing模式对应的交换机类型是direct,和发布订阅模式的区别在于:routing模式下,可以指定一个routingkey,用于区分消息
生产者
var channel = conn.CreateModel();
//定义交换机
channel.ExchangeDeclare(TESTEXCHANGE, ExchangeType.Direct, true, false);
//绑定队列到交换机
Console.WriteLine("输入生产内容:");
var input = Console.ReadLine();
channel.BasicPublish(TESTEXCHANGE, "INFO", null, Encoding.Default.GetBytes("hello rabbitmq:" + input));
消费者 A
//定义队列
channel.QueueDeclare(QUEUENAME, true, false, false);
//定义交换机
channel.ExchangeDeclare(TESTEXCHANGE, ExchangeType.Direct, true, false);
//绑定队列到交换机
channel.QueueBind(QUEUENAME, TESTEXCHANGE, "INFO");
消费者 B
//定义队列
channel.QueueDeclare(QUEUENAME, true, false, false);
//定义交换机
channel.ExchangeDeclare(TESTEXCHANGE, ExchangeType.Direct, true, false);
//绑定队列到交换机
channel.QueueBind(QUEUENAME, TESTEXCHANGE, "ERROR");
绑定成功后,发送消息,消费者A可以收到消息,消费者B无法收到消息。
如果遇到指定routingKey生产一条消息,结果 AB消费者都收到的情况。建议在RabbitMQ后台的交换机下看一下绑定的Queue是否重复绑定了多个routingKey.
topic通配符模式
在通配符模式下,RabbitMQ使用模糊匹配来决定把消息推送给哪个生产者。通配符有两个符号来匹配routingKey
- *匹配一个字符 如:*.qq.com 可匹配 1.qq.com
- #匹配一个或者多个字符。 如:*.qq.com 可匹配 1.qq.com或者1111.qq.com
其他的操作基本和routing模式一样。
header模式
header模式是把routingkey放到header中.取消掉了routingKey。并使用一个字典传递 K、V的方式来匹配。
比如同时要给用户发送邮件和短信,可直接通过header的键值对来匹配绑定的值,把消息传递给发短信和邮件的生产者.
广告时间:
成都南门这边有招BS方向高级.NET程序员的公司吗? 有的话,请私聊我。或者加我QQ:862640563
博客地址:https://www.cnblogs.com/boxrice/ 转载请注明出处
抽一根烟的时间学会.NET Core 操作RabbitMQ的更多相关文章
- SQL Server Management Studio 无法修改表,超时时间已到 在操作完成之前超时时
在修改表时,保存的时候显示:无法修改表,超时时间已到 在操作完成之前超时时间已过或服务器未响应 这是执行时间设置过短的原因,可以修改一下设置便能把执行时间加长,以便有足够的时间执行完修改动作. 在 S ...
- 前端和后台对时间数值的增减操作(JavaScript和C#两种方法)
最近在做一个视频回放项目,记录下一点总结. 应用背景: 假设有一个门禁系统记录着门禁的人员进出刷卡信息,门禁装有视频录像设备,现在要根据人员的刷卡时间调出其刷卡时间点前后一段时间的录像.关于视频回放部 ...
- timeout Timeout时间已到.在操作完成之前超时时间已过或服务器未响应
Timeout时间已到.在操作完成之前超时时间已过或服务器未响应 问题 在使用asp.net开发的应用程序查询数据的时候,遇到页面请求时间过长且返回"Timeout时间已到.在操作完成之间超 ...
- (摘)timeout Timeout时间已到.在操作完成之前超时时间已过或服务器未响应的几种情况
Timeout时间已到.在操作完成之前超时时间已过或服务器未响应 问题 在使用asp.net开发的应用程序查询数据的时候,遇到页面请求时间过长且返回"Timeout时间已到.在操作完成之间超 ...
- [转]三分钟学会.NET Core Jwt 策略授权认证
[转]三分钟学会.NET Core Jwt 策略授权认证 一.前言# 大家好我又回来了,前几天讲过一个关于Jwt的身份验证最简单的案例,但是功能还是不够强大,不适用于真正的项目,是的,在真正面对复杂而 ...
- poj2509---抽k根烟就换一支,求能抽烟的总数
#include <stdio.h> #include <stdlib.h> int main() { int now,k; while(scanf("%d %d&q ...
- 一支烟的时间导致他错失女神,Python查看撤回消息,力挽狂澜!
2011年1月21日 微信(WeChat) 是腾讯公司于2011年1月21日推出的一个为智能终端提供即时通讯服务的免费应用程序,由张小龙所带领的腾讯广州研发中心产品团队打造 .在互联网飞速发展的下.民 ...
- SqlServer2008 无法修改表,超时时间已到 在操作完成之前超时解决方法
在 SQL Server Management Studio 里, 通过菜单“工具-选项”打开选项对话框. 在左侧寻找“设计器-表设计器和数据库设计器”, 然后在右侧勾选“为表设计器更新重写连接字符串 ...
- 十分钟学会mysql数据库操作
Part1:写在最前 MySQL安装的方式有三种: ①rpm包安装 ②二进制包安装 ③源码安装 这里我们推荐二进制包安装,无论从安装速度还是用于生产库安装环境来说,都是没问题的.现在生产库一般采用My ...
随机推荐
- P1108 低价购买(DP)
题目描述 "低价购买"这条建议是在奶牛股票市场取得成功的一半规则.要想被认为是伟大的投资者,你必须遵循以下的问题建议:"低价购买:再低价购买".每次你购买一支股 ...
- AtCoder Beginner Contest 183 E - Queen on Grid (DP)
题意:有一个\(n\)x\(m\)的棋盘,你需要从\((1,1)\)走到\((n,m)\),每次可以向右,右下,下走任意个单位,\(.\)表示可以走,#表示一堵墙,不能通过,问从\((1,1)\)走\ ...
- Kuroni and the Punishment CodeForces - 1305F 随机函数mt19937 + 质因子分解
题意: 给你n个数,你每次操作可以对一个数加1或者减1,让你求你最少需要操作多少次可以使这n个数的公因子大于1 题解: 正常方法就是枚举质因子(假设质因子为x),然后对于这个数组中的数a[i],让a[ ...
- Codeforces Round #669 (Div. 2) C. Chocolate Bunny (交互,构造)
题意:有一个长度为\(n\)的隐藏序列,你最多可以询问\(2n\)次,每次可以询问\(i\)和\(j\)位置上\(p[i]\ mod\ p[j]\)的结果,询问的格式是\(?\ x\ y\),如果已经 ...
- MSE,RMSE
MSE: Mean Squared Error 均方误差是指参数估计值与参数真值之差平方的期望值; MSE可以评价数据的变化程度,MSE的值越小,说明预测模型描述实验数据具有更好的精确度. RMSE ...
- sizeof和strlen在string类中的使用
字符串的sizeof和strlen 考虑下面的问题: char a[] = "abcdef"; char b[20] = "abcdef"; string s ...
- MATLAB中将mat文件转为txt格式文件
直接保存为txt文件: 可以用fprintf函数,来代替save函数 比如现在我有一个变量a=[0.1223 345.4544] 如果我想保存它的话,可以用下面的程序: fid = fopen(' ...
- SPOJ VLATTICE Visible Lattice Points(莫比乌斯反演)题解
题意: 有一个\(n*n*n\)的三维直角坐标空间,问从\((0,0,0)\)看能看到几个点. 思路: 按题意研究一下就会发现题目所求为. \[(\sum_{i=1}^n\sum_{j=1}^n\su ...
- 计蒜客第五场 UCloud 的安全秘钥(中等) (尺取游标法
每个 UCloud 用户会构造一个由数字序列组成的秘钥,用于对服务器进行各种操作.作为一家安全可信的云计算平台,秘钥的安全性至关重要.因此,UCloud 每年会对用户的秘钥进行安全性评估,具体的评估方 ...
- 手工数据结构系列-C语言模拟队列和栈 hdu1702
#include <stdio.h> #include <stdlib.h> //================= DATA STRUCTURE ============== ...