十五、.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 ...
随机推荐
- JQuery跨站脚本漏洞
原理: jQuery中过滤用户输入数据所使用的正则表达式存在缺陷,可能导致 location.hash 跨站漏洞 影响版本: jquery-1.7.1~1.8.3 jquery-1.6.min.js, ...
- LeetCode---84. 柱状图中最大的矩形(hard)
题目:84. 柱状图中最大的矩形 给定 n 个非负整数,用来表示柱状图中各个柱子的高度.每个柱子彼此相邻,且宽度为 1 . 求在该柱状图中,能够勾勒出来的矩形的最大面积. 示例: 输入: [2,1,5 ...
- 2 IDEA——新建一个java项目
快捷键 public class Hello { // psvm public static void main(String[] args) { // sout System.out.println ...
- IO异步,读写压缩文件,监控文件系统
这节结尾IO,讲一下异步操作文件,读写压缩文件,监控文件系统这三个知识点. 异步操作文件: 说到异步,必然要了解的是async和await这两个关键字(异步详情点击基于任务的异步编程(Task ...
- where优先级
select name from emply where id >5; 先找表from emply 再找条件 where id >5 最后打印 你想打印的字段 可以把select看成打印 ...
- [刷题] 77 Combinations
要求 给出两个整数n和k,在n个数字中选出k个数字的所有组合 示例 n=4 , k=2 [ [ 1, 2 ] , [ 1, 3 ] , [ 1, 4 ] , [ 2, 3 ] , [ 2, 4 ] , ...
- mysqldMY-010457] [Server] --initialize specified but the data directory has files in it. Aborting. 2020-12
删除mysql的/var/lib/mysql目录下的所有文件 https://blog.csdn.net/tr1912/article/details/81271851 # mysqld --init ...
- 【Git】git clone报错 git fatal: Unable to find remote helper for 'https'
[参考资料] https://stackoverflow.com/questions/8329485/unable-to-find-remote-helper-for-https-during-git ...
- Docker Swarm(六)Label 节点标签与服务约束
前言 多节点 Swarm 集群下,可能节点的配置不同(比如 CPU.内存等),部署着不同类型的服务(比如 Web服务.Job服务等),当这些服务以 Service 或者 Stack 的形式部署到集群, ...
- ssh判断免密登陆
ssh判断免密登陆 [root@jenkins ~]# vi /opt/release_code.sh #!/bin/bash . /etc/init.d/functions #echo $WORKS ...