LiXiang98

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
统计
 

一、序言

在DDD领域驱动设计中,有领域事件和集成事件。领域事件是微服务(进程)内部的消息通信,我们可以选用MeditR进行消息通信。集成事件可以理解成是服务之间的消息通信,需要借助消息中间件进行信息交换,常见的消息中间件有Kafka、RabbitMQ、ActiveMQ等,这里主要记录RabbitMQ Routing模式的基本使用。

二、基本概念

RabbitMQ是实现了高级消息队列协议(AMQP)的开源消息代理软件(亦称面向消息的中间件),Routing模式的好处是生产者消费者宕机,消息只要发送了都在队列中,不会存在消息的丢失。

2.1信道(Channel)

信道是消息的生产者、消费者和服务器进行通信的虚拟连接。TCP连接的建立是非常消耗资源的,所以RabbitMQ在TCP连接的基础上构建了虚拟的信道。我们尽量重复使用TCP连接,而信道则可以用完了就关闭。

2.2队列(Queue)

用来进行消息收发的地方,生产者讲消息放到队列中,消费者从队列中获取数据。

2.3交换机(exchange)

把消息路由到一个或多个队列中。

2.4绑定(binding)

把交换机和队列按照路由规则绑定起来。

2.5路由关键字(Routing Key)

交换机根据这个关键字进行消息投递。

三、基本使用

3.1安装RabbitMQ服务器

linux和windows服务器安装方式不一样,网上很多教程,在此略过。

3.2创建消息生产者项目

  1. 通过nuget装RabbitMQ.Client
  2. 编写发送消息代码
var factory = new ConnectionFactory();
factory.HostName="127.0.0.1";//RabbitMQ服务器地址
factory.DispatchConsumersAsync = true;//允许异步
var connection = factory.CreateConnection();//创建连接
string exchangeName = "Exchange1";//交换机名字
string routingKey = "routingKey";//路由关键字
while(true)
{
	using var channel = connection.CreateModel();//创建信道
	var prop = channel.CreateBasicProperties();//创建属性
	prop.DeliverMode = 2;
	channel.ExchangeDeclare(exchange:exchangeName,type:"direct");//声明交换机
	byte[] body = Encoding.UTF8.GetBytes(DateTime.Now.ToString());
	channel.BasicPublish(exchangeName,routingKey,mandatory:true,basicProperties:prop,body:body);
	Thread.Sleep(1000);
}

3.3创建消息消费者项目

  1. 通过nuget装RabbitMQ.Client
  2. 编写消费消息代码
var factory = new ConnectionFactory();
factory.HostName="127.0.0.1";//RabbitMQ服务器地址
factory.DispatchConsumersAsync = true;//允许异步
var connection = factory.CreateConnection();//创建连接
string exchangeName = "Exchange1";//交换机名字
string routingKey = "routingKey";//路由关键字
string queueName="queue1";//队列名
using var channel = connection.CreateModel();//创建信道
channel.ExchangeDeclare(exchange:exchangeName,type:"direct");//声明交换机
//消费者需要知道routingKey和exchangeName
channel.QueueDeclare(queue:queueName,durable:true,exclusive:false,autoDelete:false,arguments:null);//声明队列
channel.QueueBind(queue:queueName,exchange:exchangeName,routingKey:routingKey);//把交换机和队列按照路由规则绑定(生产者发送消息时没有找到routingKey绑定的队列的消息会被舍弃掉)

var consumer = new AsyncEventingBasicConsumer(channel);
consumer.Received+=Consumer_Received;
channel.BasicConsume(queueName,false,consumer);
//received事件
async Task Consumer_Recieved(object sender,BasicDeliverEventArgs args)
{
	try
	{
		var bytes = args.Body.ToArray();
		string msg = Encoding.UTF8.GetString(bytes);
		Console.WriteLine("收到了消息"+msg);
		channel.BasicAck(args.DeliveryTag,multiple:false);//消息确认,(处理到一半宕机)对于没有确认的消息,会重发。
		await Task.Delay(1000);
	}
	catch(Exception ex)
	{
		channel.BasicReject(args.DeliveryTag,true);//失败重发
		Console.WriteLine("处理收到的消息失败"+ex);
	}
}
posted on   LiXiang98  阅读(181)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
 
点击右上角即可分享
微信分享提示