十五、.net core(.NET 6)搭建RabbitMQ消息队列生产者和消费者的简单方法
搭建RabbitMQ简单通用的直连方法
如果还没有MQ环境,可以参考上一篇的博客,在windows系统上的rabbitmq环境搭建。如果使用docker环境,可以直接百度一下,应该就一个语句就可以搞定。使用windows环境安装mq有关的教程地址:
https://www.cnblogs.com/weskynet/p/14877932.html
接下来开始.net core操作Rabbitmq有关的内容。我打算使用比较简单的单机的direct直连模式,来演示一下有关操作,基本套路差不多。
首先,我在我的package包项目上面,添加对RabbitMQ.Client的引用:

在Common文件夹下,新建类库项目 Wsk.Core.RabbitMQ,并且引用package项目:

在启动项目下的appsettings配置文件里面,新增一个访问RabbitMQ的配置信息:

配置部分代码:
"MQ": [
{
"Host": "127.0.0.1", // MQ安装的实际服务器IP地址
"Port": 5672, // 服务端口号
"User": "wesky", // 用户名
"Password": "wesky123", // 密码
"ExchangeName": "WeskyExchange", // 设定一个Exchange名称,
"Durable": true // 是否启用持久化
}
]
然后,在实体类项目下,新建实体类MqConfigInfo,用于把读取的配置信息赋值到该实体类下:

实体类代码:

public class MqConfigInfo
{
public string Host { get; set; }
public int Port { get; set; }
public string User { get; set; }
public string Password { get; set; }
public string ExchangeName { get; set; }
public bool Durable { get; set; }
}
在刚刚新建的RabbitMQ类库项目下面,引用该实体类库项目,以及APppSettings项目。然后新建一个类,叫做ReadMqConfigHelper,以及它的interface接口,并且提供一个方法,叫ReadMqConfig,用来进行读取配置信息使用:

读取配置信息类代码:

public class ReadMqConfigHelper:IReadMqConfigHelper
{
private readonly ILogger<ReadMqConfigHelper> _logger;
public ReadMqConfigHelper(ILogger<ReadMqConfigHelper> logger)
{
_logger = logger;
}
public List<MqConfigInfo> ReadMqConfig()
{
try
{
List<MqConfigInfo> config = AppHelper.ReadAppSettings<MqConfigInfo>(new string[] { "MQ" }); // 读取MQ配置信息
if (config.Any())
{
return config;
}
_logger.LogError($"获取MQ配置信息失败:没有可用数据集");
return null;
}
catch (Exception ex)
{
_logger.LogError($"获取MQ配置信息失败:{ex.Message}");
return null;
}
}
}
接着,新建类MqConnectionHelper以及接口IMqConnectionHelper,用于做MQ连接、创建生产者和消费者等有关操作:

然后,新增一系列创建连接所需要的静态变量:

然后,设置两个消费者队列,用来测试。以及添加生产者连接有关的配置和操作:

然后,创建消费者连接方法:


其中,StartListener下面提供了事件,用于手动确认消息接收。如果设置为自动,有可能导致消息丢失:

然后,添加消息发布方法:

在interface接口里面,添加有关的接口,用于等下依赖注入使用:

连接类部分的代码:

public class MqConnectionHelper:IMqConnectionHelper
{ private readonly ILogger<MqConnectionHelper> _logger;
public MqConnectionHelper(ILogger<MqConnectionHelper> logger)
{
_logger = logger; _connectionReceiveFactory = new IConnectionFactory[_costomerCount];
_connectionReceive = new IConnection[_costomerCount];
_modelReceive = new IModel[_costomerCount];
_basicConsumer = new EventingBasicConsumer[_costomerCount]; } /*
备注:使用数组的部分,是给消费端用的。目前生产者只设置了一个,消费者可能存在多个。
当然,有条件的还可以上RabbitMQ集群进行处理,会更好玩一点。
*/
private static IConnectionFactory _connectionSendFactory; //RabbitMQ工厂 发送端
private static IConnectionFactory[] _connectionReceiveFactory; //RabbitMQ工厂 接收端 private static IConnection _connectionSend; //连接 发送端
private static IConnection[] _connectionReceive; //连接 消费端 public static List<MqConfigInfo> _mqConfig; // 配置信息 private static IModel _modelSend; //通道 发送端
private static IModel[] _modelReceive; //通道 消费端 private static EventingBasicConsumer[] _basicConsumer; // 事件 /* 设置两个routingKey 和 队列名称,用来做测试使用*/
public static int _costomerCount = 2;
public static string[] _routingKey = new string[] {"WeskyNet001","WeskyNet002" };
public static string[] _queueName = new string[] { "Queue001", "Queue002" }; /// <summary>
/// 生产者初始化连接配置
/// </summary>
public void SendFactoryConnectionInit()
{
_connectionSendFactory = new ConnectionFactory
{
HostName = _mqConfig.FirstOrDefault().Host,
Port = _mqConfig.FirstOrDefault().Port,
UserName = _mqConfig.FirstOrDefault().User,
Password = _mqConfig.FirstOrDefault().Password
};
} /// <summary>
/// 生产者连接
/// </summary>
public void SendFactoryConnection()
{ if (null != _connectionSend && _connectionSend.IsOpen)
{
return; // 已有连接
}
_connectionSend = _connectionSendFactory.CreateConnection(); // 创建生产者连接 if (null != _modelSend && _modelSend.IsOpen)
{
return; // 已有通道
}
_modelSend = _connectionSend.CreateModel(); // 创建生产者通道 _modelSend.ExchangeDeclare(_mqConfig.FirstOrDefault().ExchangeName, ExchangeType.Direct); // 定义交换机名称和类型(direct) } /// <summary>
/// 消费者初始化连接配置
/// </summary>
public void ReceiveFactoryConnectionInit()
{
var factories = new ConnectionFactory
{
HostName = _mqConfig.FirstOrDefault().Host,
Port = _mqConfig.FirstOrDefault().Port,
UserName = _mqConfig.FirstOrDefault().User,
Password = _mqConfig.FirstOrDefault().Password
}; for (int i = 0; i < _costomerCount; i++)
{
_connectionReceiveFactory[i] = factories; // 给每个消费者绑定一个连接工厂
}
} /// <summary>
/// 消费者连接
/// </summary>
/// <param name="consumeIndex"></param>
/// <param name="exchangeName"></param>
/// <param name="routeKey"></param>
/// <param name="queueName"></param>
public void ConnectionReceive(int consumeIndex, string exchangeName, string routeKey, string queueName)
{
_logger.LogInformation($"开始连接RabbitMQ消费者:{routeKey}"); if (null != _connectionReceive[consumeIndex] && _connectionReceive[consumeIndex].IsOpen)
{
return;
}
_connectionReceive[consumeIndex] = _connectionReceiveFactory[consumeIndex].CreateConnection(); // 创建消费者连接 if (null != _modelReceive[consumeIndex] && _modelReceive[consumeIndex].IsOpen)
{
return;
}
_modelReceive[consumeIndex] = _connectionReceive[consumeIndex].CreateModel(); // 创建消费者通道 _basicConsumer[consumeIndex] = new EventingBasicConsumer(_modelReceive[consumeIndex]); _modelReceive[consumeIndex].ExchangeDeclare(exchangeName, ExchangeType.Direct); // 定义交换机名称和类型 与生产者保持一致 _modelReceive[consumeIndex].QueueDeclare(
queue: queueName, //消息队列名称
durable: _mqConfig.FirstOrDefault().Durable, // 是否可持久化,此处配置在文件中,默认全局持久化(true),也可以自定义更改
exclusive: false,
autoDelete: false,
arguments: null
); // 定义消费者队列 _modelReceive[consumeIndex].QueueBind(queueName, exchangeName, routeKey); // 队列绑定给指定的交换机 _modelReceive[consumeIndex].BasicQos(0, 1, false); // 设置消费者每次只接收一条消息 StartListener((model, ea) =>
{
byte[] message = ea.Body.ToArray(); // 接收到的消息 string msg = Encoding.UTF8.GetString(message); _logger.LogInformation($"队列{queueName}接收到消息:{msg}");
Thread.Sleep(2000); _modelReceive[consumeIndex].BasicAck(ea.DeliveryTag, true);
}, queueName, consumeIndex); } /// <summary>
/// 消费者接收消息的确认机制
/// </summary>
/// <param name="basicDeliverEventArgs"></param>
/// <param name="queueName"></param>
/// <param name="consumeIndex"></param>
private static void StartListener(EventHandler<BasicDeliverEventArgs> basicDeliverEventArgs, string queueName, int consumeIndex)
{
_basicConsumer[consumeIndex].Received += basicDeliverEventArgs;
_modelReceive[consumeIndex].BasicConsume(queue: queueName, autoAck: false, consumer: _basicConsumer[consumeIndex]); // 设置手动确认。 } /// <summary>
/// 消息发布
/// </summary>
/// <param name="message"></param>
/// <param name="exchangeName"></param>
/// <param name="routingKey"></param>
public static void PublishExchange(string message, string exchangeName, string routingKey = "")
{
byte[] body = Encoding.UTF8.GetBytes(message);
_modelSend.BasicPublish(exchangeName, routingKey, null, body);
} }
现在,我把整个Wsk.Core.RabbitMQ项目进行添加到依赖注入:

然后,在启动项目里面的初始化服务里面,添加对MQ连接的初始化以及连接,并且发送两条消息进行测试:

启用程序,提示发送成功:

打开RabbitMQ页面客户端,可以看见新增了一个交换机WeskyExchange:

点进去可以看见对应的流量走势:

关闭程序,现在添加消费者的初始化和连接,然后重新发送:

可见发送消息成功,并且消费者也成功接收到了消息。打开客户端查看一下:

在WeskyExchange交换机下,多了两个队列,以及队列归属的RoutingKey分别是WeskyNet001和WeskyNet002。以及在Queue目录下,多了两个队列的监控信息:

为了看出点效果,我们批量发消息试一下:

然后启动项目,我们看一下监控效果。先是交换机页面的监控:

然后是队列1的监控:

现在换一种写法,在消费者那边加个延迟:

并且生产者的延迟解除:

再启动一下看看效果:

会发现队列消息被堵塞,必须在执行完成以后,才可以解锁。而且生产者这边并不需要等待,可以看见消息一次性全发出去了,可以继续执行后续操作:

以上就是关于使用Direct模式进行RabbitMQ收发消息的内容,发送消息可以在其他类里面或者方法里面,直接通过静态方法进行发送;接收消息,启动了监听,就可以一直存活。如果有兴趣,也可以自己尝试Fanout、Topic等不同的模式进行测试,以及可以根据不同的机器,进行配置成收发到不同服务器上面进行通信。
十五、.net core(.NET 6)搭建RabbitMQ消息队列生产者和消费者的简单方法的更多相关文章
- RabbitMQ消息队列生产者和消费者
概述 生产者生产数据至 RabbitMQ 队列,消费者消费 RabbitMQ 队列里的数据. 详细 代码下载:http://www.demodashi.com/demo/10723.html 一.准备 ...
- 基于ASP.NET Core 5.0使用RabbitMQ消息队列实现事件总线(EventBus)
文章阅读请前先参考看一下 https://www.cnblogs.com/hudean/p/13858285.html 安装RabbitMQ消息队列软件与了解C#中如何使用RabbitMQ 和 htt ...
- RabbitMQ消息队列之二:消费者和生产者
在使用RabbitMQ之前,需要了解RabbitMQ的工作原理. RabbitMQ的工作原理 RabbitMQ是消息代理.从本质上说,它接受来自生产者的信息,并将它们传递给消费者.在两者之间,它可以根 ...
- .net core使用rabbitmq消息队列 (二)
之前有写过.net core集成使用rabbitmq的博文,见.net core使用rabbitmq消息队列,但是里面的使用很简单,而且还有几个bug,想改下,但是后来想了想,还是算了,之前使用的是. ...
- RabbitMQ消息队列1: Detailed Introduction 详细介绍
1. 历史 RabbitMQ是一个由erlang开发的AMQP(Advanced Message Queue )的开源实现.AMQP 的出现其实也是应了广大人民群众的需求,虽然在同步消息通讯的世界里有 ...
- (十)RabbitMQ消息队列-高可用集群部署实战
原文:(十)RabbitMQ消息队列-高可用集群部署实战 前几章讲到RabbitMQ单主机模式的搭建和使用,我们在实际生产环境中出于对性能还有可用性的考虑会采用集群的模式来部署RabbitMQ. Ra ...
- .net core使用rabbitmq消息队列
看博文的朋友,本文有些过时了,还有些BUG,如果想了解更多用法,看看这篇吧:.net core使用rabbitmq消息队列 (二) 首先,如果你还没有安装好rabbitmq,可以参考我的博客: Ubu ...
- (十四)RabbitMQ消息队列-启用SSL安全通讯
原文:(十四)RabbitMQ消息队列-启用SSL安全通讯 如果RabbitMQ服务在内网中,只有内网的应用连接,我们认为这些连接都是安全的,但是个别情况我们需要让RabbitMQ对外提供服务.这种情 ...
- (十二)RabbitMQ消息队列-性能测试
原文:(十二)RabbitMQ消息队列-性能测试 硬件配置 宿主机用的联想3850X6的服务器四颗E7-4850v3的处理器,DDR4内存,两块1.25TB的pcie固态.在宿主机上使用的事esxi5 ...
随机推荐
- SMTP、POP3和IMAP邮件协议
目录 SMTP POP IMAP 总结 DNS记录中的MX记录 今天入职第一天,公司让配置个人的内网.外网邮箱,这可把我给搞晕了,本来以前就对邮箱这块不是很了解,平时也不怎么用邮箱,顶多有个QQ邮箱而 ...
- python中实现打印特定字符变换
首先需要将 lib文件 放在该文件同一目录 使用的时候,先导入 from lib.common import print_msg ,然后调用里面的 print_msg() 方法即可! lib文件地址: ...
- Windows PE变形练手3-把通用模板机器码直接覆盖目标PE
把通用模板机器码直覆盖目标PE 这个地方真是尝试了好久,遇到很多坑点,Win PE那本书上的东西有点不够,也就直接写书上的例子会发现很多地方不是说的那样,里面提供的信息太少了,就比如里面并没有提被注入 ...
- HellowWorld详解
1.随便新建一个文件夹,存放代码 2.在文件夹中新建一个Java文件 新建一个.txt文本文档-->将扩展名.txt修改为.java 注:如果创建的文本文档没有显示扩展名,则有如下方法: 方法一 ...
- L SERVER 数据库被标记为“可疑”的解决办法
问题背景: 日常对Sql Server 2005关系数据库进行操作时,有时对数据库(如:Sharepoint网站配置数据库名Sharepoint_Config)进行些不正常操作如数据库在读写时而无故停 ...
- (一)RabbitMQ安装与基本配置
[博主使用的环境是阿里云ecs服务器,操作系统为centos] 安装erlang环境 RabbitMQ底层是Erlang语言,因此要先安装erlang环境,就像你要运行Java程序就必须先安装JRE/ ...
- java设计模式之单例模式你真的会了吗?(懒汉式篇)
java设计模式之单例模式你真的会了吗?(懒汉式篇) 一.什么是单例模式? 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一.这种类型的设计模式属于创建型模式,它提供 ...
- [操作系统知识储备,进程相关概念,开启进程的两种方式、 进程Queue介绍]
[操作系统知识储备,进程相关概念,开启进程的两种方式.进程Queue介绍] 操作系统知识回顾 为什么要有操作系统. 程序员无法把所有的硬件操作细节都了解到,管理这些硬件并且加以优化使用是非常繁琐的工作 ...
- JAVA 面试相关
1. int和Integer有什么区别? 答:Java是一个近乎纯洁的面向对象编程语言,但是为了编程的方便还是引入了基本数据类型,但是为了能够将这些基本数据类型当成对象操作,Java为每一个基本数据类 ...
- Envoy:离群点检测 outlier detection
outlier detection 在异常检测领域中,常常需要决定新观察的点是否属于与现有观察点相同的分布(则它称为inlier),或者被认为是不同的(称为outlier).离群是异常的数据,但是不一 ...