搭建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消息队列生产者和消费者的简单方法的更多相关文章

  1. RabbitMQ消息队列生产者和消费者

    概述 生产者生产数据至 RabbitMQ 队列,消费者消费 RabbitMQ 队列里的数据. 详细 代码下载:http://www.demodashi.com/demo/10723.html 一.准备 ...

  2. 基于ASP.NET Core 5.0使用RabbitMQ消息队列实现事件总线(EventBus)

    文章阅读请前先参考看一下 https://www.cnblogs.com/hudean/p/13858285.html 安装RabbitMQ消息队列软件与了解C#中如何使用RabbitMQ 和 htt ...

  3. RabbitMQ消息队列之二:消费者和生产者

    在使用RabbitMQ之前,需要了解RabbitMQ的工作原理. RabbitMQ的工作原理 RabbitMQ是消息代理.从本质上说,它接受来自生产者的信息,并将它们传递给消费者.在两者之间,它可以根 ...

  4. .net core使用rabbitmq消息队列 (二)

    之前有写过.net core集成使用rabbitmq的博文,见.net core使用rabbitmq消息队列,但是里面的使用很简单,而且还有几个bug,想改下,但是后来想了想,还是算了,之前使用的是. ...

  5. RabbitMQ消息队列1: Detailed Introduction 详细介绍

    1. 历史 RabbitMQ是一个由erlang开发的AMQP(Advanced Message Queue )的开源实现.AMQP 的出现其实也是应了广大人民群众的需求,虽然在同步消息通讯的世界里有 ...

  6. (十)RabbitMQ消息队列-高可用集群部署实战

    原文:(十)RabbitMQ消息队列-高可用集群部署实战 前几章讲到RabbitMQ单主机模式的搭建和使用,我们在实际生产环境中出于对性能还有可用性的考虑会采用集群的模式来部署RabbitMQ. Ra ...

  7. .net core使用rabbitmq消息队列

    看博文的朋友,本文有些过时了,还有些BUG,如果想了解更多用法,看看这篇吧:.net core使用rabbitmq消息队列 (二) 首先,如果你还没有安装好rabbitmq,可以参考我的博客: Ubu ...

  8. (十四)RabbitMQ消息队列-启用SSL安全通讯

    原文:(十四)RabbitMQ消息队列-启用SSL安全通讯 如果RabbitMQ服务在内网中,只有内网的应用连接,我们认为这些连接都是安全的,但是个别情况我们需要让RabbitMQ对外提供服务.这种情 ...

  9. (十二)RabbitMQ消息队列-性能测试

    原文:(十二)RabbitMQ消息队列-性能测试 硬件配置 宿主机用的联想3850X6的服务器四颗E7-4850v3的处理器,DDR4内存,两块1.25TB的pcie固态.在宿主机上使用的事esxi5 ...

随机推荐

  1. Wordpress主题编辑器漏洞复现

    Wordpress是全球流行的博客网站,全球有上百万人使用它来搭建博客.他使用PHP脚本和Mysql数据库来搭建网站. 那么,如果当我们在渗透测试过程中获得到了别人Wordpress的账号和密码之后, ...

  2. 浅谈自动特征构造工具Featuretools

    简介 特征工程在机器学习中具有重要意义,但是通过手动创造特征是一个缓慢且艰巨的过程.Python的特征工程库featuretools可以帮助我们简化这一过程.Featuretools是执行自动化特征工 ...

  3. Outlook关闭时最小化

    一:背景环境: 当使用Outlook的时候,不小心点关闭,会不能及时发现接收的新邮件. 二:解决方法: 利用KeepOutlookRunning.dll插件,可以实现,点击关闭时,outlook没有实 ...

  4. TLS是如何保障数据传输安全(中间人攻击)

    前言 前段时间和同事讨论HTTPS的工作原理,当时对这块知识原理掌握还是靠以前看了一些博客介绍,深度不够,正好我这位同事是密码学专业毕业的,结合他密码学角度对tls加解密这阐述,让我对这块原理有了更进 ...

  5. 线程本地存储(动态TLS和静态TLS)

    线程本地存储(TLS) 对于多线程应用程序,如果线程过于依赖全局变量和静态局部变量就会产生线程安全问题.也就是一个线程的使用全局变量可能会影响到其他也使用此全局变量的线程,有可能会造成一定的错误,这可 ...

  6. 【tee小白的第一篇随笔】keystone代码略读

    武大信安在读,最近在自学Risc-v架构的可信执行环境. (实验报告多半是为了交差.临时起意写写博客,分享一些自己读代码的心得理解.) 本篇内容由队和我友总结而成,如有错误欢迎指正交流. keysto ...

  7. 关于MySQL参数,这些你要知道

    前言: 在前面一些文章中,经常能看到介绍某某参数的作用,可能有些小伙伴仍搞不清楚 MySQL 参数是啥.本篇文章我们来聊聊 MySQL 参数,学习下如何管理维护 MySQL 参数. 1.MySQL参数 ...

  8. 消息队列RabbitMQ(五):死信队列与延迟队列

    死信队列 引言 死信队列,英文缩写:DLX .Dead Letter Exchange(死信交换机),其实应该叫做死信交换机才更恰当. 当消息成为Dead message后,可以被重新发送到另一个交换 ...

  9. istio部署问题Q&A

    端口绑定无权限 创建Gateway,提示绑定端口无权限. 2020-12-27T12:25:30.974288Z warning envoy config gRPC config for type.g ...

  10. [Java] Solr & Elasticsearch

    背景 实现网站自带的搜索功能,如淘宝中的商品搜索 全文搜索 数据分类 结构化数据:固定格式或长度有限的数据,如数据库.元数据等 非结构化数据:不定长或无固定格式的数据,如邮件.word文档等 搜索分类 ...