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

  由于代码比较多,我把代码传到gitee上了,地址见:https://gitee.com/shanfeng1000/dotnetcore-demo/tree/master/Rabbitmq

  这是一个Demo项目,介绍.net core集成使用rabbitmq消息队列,使用的.net core 3.1,这里简单介绍:

  生产者(AspNetCore.WebApi.Producer)

  在Startup的ConfigureServices方法中添加相关rabbitmq的服务:  

  

    public void ConfigureServices(IServiceCollection services)
{
string[] hosts = new string[] { "192.168.209.133", "192.168.209.134", "192.168.209.135" };
int port = 5672;
string userName = "admin";
string password = "123456";
string virtualHost = "/";
var arguments = new Dictionary<string, object>() { { "x-queue-type", "classic" } }; #region 日志记录 services.AddLogging(builder =>
{
builder.SetMinimumLevel(LogLevel.Trace);
});
services.AddRabbitLogger(options =>
{
options.Hosts = hosts;
options.Password = password;
options.Port = port;
options.UserName = userName;
options.VirtualHost = virtualHost; options.Arguments = arguments;
options.Durable = true;
options.AutoDelete = true; options.Category = "Home";
options.MinLevel = LogLevel.Trace;
options.ApplicationName = "AspNetCore.WebApi.Producer"; //队列模式
options.Queue = "queue.logger"; //交换机模式
//options.Exchange = "exchange.logger";
//options.RouteQueues = new RouteQueue[] { new RouteQueue() { Queue = "queue.logger", Route = "#" } };
//options.Type = RabbitExchangeType.Topic;
}); #endregion #region 普通模式 services.AddRabbitProducer("SimplePattern", options =>
{
options.Hosts = hosts;
options.Password = password;
options.Port = port;
options.UserName = userName;
options.VirtualHost = virtualHost; options.Arguments = arguments;
options.Durable = true;
options.AutoDelete = true; options.InitializeCount = 3;
options.Queues = new string[] { "queue.simple" };
}); #endregion #region 工作模式 services.AddRabbitProducer("WorkerPattern", options =>
{
options.Hosts = hosts;
options.Password = password;
options.Port = port;
options.UserName = userName;
options.VirtualHost = virtualHost; options.Arguments = arguments;
options.Durable = true;
options.AutoDelete = true; options.InitializeCount = 3;
options.Queues = new string[] { "queue.worker" };
}); #endregion #region 发布订阅模式 services.AddRabbitProducer("FanoutPattern", options =>
{
options.Hosts = hosts;
options.Password = password;
options.Port = port;
options.UserName = userName;
options.VirtualHost = virtualHost; options.Arguments = arguments;
options.Durable = true;
options.AutoDelete = true; options.InitializeCount = 3;
options.RouteQueues = new RouteQueue[] { new RouteQueue() { Queue = "queue.fanout1" }, new RouteQueue() { Queue = "queue.fanout2" } };
options.Type = RabbitExchangeType.Fanout;
options.Exchange = "exchange.fanout";
}); #endregion #region 路由模式 services.AddRabbitProducer("DirectPattern", options =>
{
options.Hosts = hosts;
options.Password = password;
options.Port = port;
options.UserName = userName;
options.VirtualHost = virtualHost; options.Arguments = arguments;
options.Durable = true;
options.AutoDelete = true; options.InitializeCount = 5;
options.Exchange = "exchange.direct";
options.Type = RabbitExchangeType.Direct;
options.RouteQueues = new RouteQueue[] { new RouteQueue() { Queue = "queue.direct1", Route = "direct1" }, new RouteQueue() { Queue = "queue.direct2", Route = "direct2" } };
}); #endregion #region 主题模式 services.AddRabbitProducer("TopicPattern", options =>
{
options.Hosts = hosts;
options.Password = password;
options.Port = port;
options.UserName = userName;
options.VirtualHost = virtualHost; options.Arguments = arguments;
options.Durable = true;
options.AutoDelete = true; options.InitializeCount = 5;
options.RouteQueues = new RouteQueue[] { new RouteQueue() { Queue = "queue.topic1", Route = "topic1.#" }, new RouteQueue() { Queue = "queue.topic2", Route = "topic2.#" } };
options.Type = RabbitExchangeType.Topic;
options.Exchange = "exchange.topic";
}); #endregion ......
}

ConfigureServices

  里面介绍了6中集成方式:

  使用AddRabbitLogger方法添加日志相关的服务,需要注意的是,数据是以json格式发送到rabbitmq中去的,具体可以参考RabbitLoggerMessage<T>类,最好是自己发布测试就可以了,当然读者可以安装自己的需求修改RabbitLogger类中的发布逻辑。

  使用AddRabbitProducer方法添加一个发布者,可以指定名称,这个名称是获取发布者对象时使用。这个方法添加的发布者可以满足rabbitmq的五种使用方式(普通模式,工作模式,发布订阅模式,路由模式,主题模式),具体由RabbitProducerOptions配置指定。

  服务配置好,具体使用可以参考HomeController,日志记录可以注入ILogger<T>对象,或者注入ILoggerFactory对象,然后获取ILogger<T>对象,直接使用ILogger<T>对象的方法就是发布消息了:  

    /// <summary>
/// 日志
/// </summary>
/// <param name="message"></param>
/// <returns></returns>
[HttpGet]
public string Get(string message)
{
logger.LogTrace($"Trace:{message}");
logger.LogDebug($"Debug:{message}");
logger.LogInformation($"Information:{message}");
logger.LogWarning($"Warning:{message}");
logger.LogError($"Error:{message}");
logger.LogCritical($"Critical:{message}"); return "success";

  至于另外五种模式,我们需要注入IRabbitProducerFactory对象,然后使用Create方法创建指定名称的发布者,然后调用Publish或者PublishAsync方法发布消息,而且他们都有几个重载。

  需要注意的是,不同类型的生产者应该使用不同的Publish或者PublishAsync方法,比如普通模式和工作模式,因为他们没有路由参数,因此需要使用无路由参数的Publish方法,如:  

    /// <summary>
/// Simple
/// </summary>
/// <returns></returns>
[HttpGet("Simple")]
public string Simple(string message = "Simple")
{
var producer = rabbitProducerFactory.Create("SimplePattern");
producer.Publish(message); return "success";
}
/// <summary>
/// Worker
/// </summary>
/// <param name="message"></param>
/// <returns></returns>
[HttpGet("Worker")]
public string Worker(string message = "Worker")
{
var producer = rabbitProducerFactory.Create("WorkerPattern");
int count = 10;
while (count-- > 0)
{
producer.Publish(message);
} return "success";
}

  而发布订阅模式、路由模式、主题模式都是有路由的(发布订阅模式的路由可以认为是空值),因此需要使用带路由参数的Publish方法:  

    /// <summary>
/// Direct
/// </summary>
/// <param name="route"></param>
/// <param name="message"></param>
/// <returns></returns>
[HttpGet("Direct")]
public string Direct(string route = "direct1", string message = "Direct")
{
var producer = rabbitProducerFactory.Create("DirectPattern");
producer.Publish(route, message); return "success";
}
/// <summary>
/// Fanout
/// </summary>
/// <param name="message"></param>
/// <returns></returns>
[HttpGet("Fanout")]
public string Fanout(string message = "Fanout")
{
var producer = rabbitProducerFactory.Create("FanoutPattern");
producer.Publish("", message);//fanout模式路由为空值 return "success";
}
/// <summary>
/// Topic
/// </summary>
/// <param name="route"></param>
/// <param name="message"></param>
/// <returns></returns>
[HttpGet("Topic")]
public string Topic(string route = "topic1.a", string message = "Topic")
{
var producer = rabbitProducerFactory.Create("TopicPattern");
producer.Publish(route, message); return "success";
}

  消费者(AspNetCore.WebApi.Consumer)

  生产者和消费者不在同一个项目中,同样的,需要先在Startup的ConfigureServices方法中添加服务:  

  

    public void ConfigureServices(IServiceCollection services)
{
string[] hosts = new string[] { "192.168.209.133", "192.168.209.134", "192.168.209.135" };
int port = 5672;
string userName = "admin";
string password = "123456";
string virtualHost = "/";
var arguments = new Dictionary<string, object>() { { "x-queue-type", "classic" } }; #region 日志记录 services.AddRabbitConsumer(options =>
{
options.Hosts = hosts;
options.Password = password;
options.Port = port;
options.UserName = userName;
options.VirtualHost = virtualHost; options.Arguments = arguments;
options.Durable = true;
options.AutoDelete = true; options.AutoAck = true; //options.FetchCount = 10;
//options.RouteQueues = new RouteQueue[] { new RouteQueue() { Queue = "queue.logger", Route = "#" } };//交换机模式
//options.Type = RabbitExchangeType.Topic;//交换机模式
}) //.AddListener("queue.logger", result =>
//{
// Console.WriteLine("Message From queue.logger:" + result.Body);
//}); .AddListener<RabbitConsumerListener>("queue.logger"); //.AddListener("exchange.logger", "queue.logger", result =>
//{
// Console.WriteLine("Message From queue.logger:" + result.Body);
//});//交换机模式 #endregion #region 普通模式 services.AddRabbitConsumer(options =>
{
options.Hosts = hosts;
options.Password = password;
options.Port = port;
options.UserName = userName;
options.VirtualHost = virtualHost; options.Arguments = arguments;
options.Durable = true;
options.AutoDelete = true; //options.FetchCount = 1;
options.AutoAck = false;
}).AddListener("queue.simple", result =>
{
Console.WriteLine("Message From queue.simple:" + result.Body);
result.Commit();
//result.RollBack();//回滚,参数表示是否重新消费
});
#endregion #region 工作模式 services.AddRabbitConsumer(options =>
{
options.Hosts = hosts;
options.Password = password;
options.Port = port;
options.UserName = userName;
options.VirtualHost = virtualHost; options.Arguments = arguments;
options.Durable = true;
options.AutoDelete = true; options.FetchCount = 2;
options.AutoAck = false;
}).AddListener("queue.worker", result =>
{
Console.WriteLine("Message From queue.worker1:" + result.Body);
result.Commit();
//result.RollBack();//回滚,参数表示是否重新消费
}).AddListener("queue.worker", result =>
{
Console.WriteLine("Message From queue.worker2:" + result.Body);
result.Commit();
//result.RollBack();//回滚,参数表示是否重新消费
});
#endregion #region 发布订阅模式 services.AddRabbitConsumer(options =>
{
options.Hosts = hosts;
options.Password = password;
options.Port = port;
options.UserName = userName;
options.VirtualHost = virtualHost; options.Arguments = arguments;
options.Durable = true;
options.AutoDelete = true; options.FetchCount = 2;
options.AutoAck = false;
options.RouteQueues = new RouteQueue[] { new RouteQueue() { Queue = "queue.fanout1" }, new RouteQueue() { Queue = "queue.fanout2" } };
options.Type = RabbitExchangeType.Fanout;
}).AddListener("exchange.fanout", "queue.fanout1", result =>
{
Console.WriteLine("Message From queue.fanout1:" + result.Body);
result.Commit();
//result.RollBack();//回滚,参数表示是否重新消费
}).AddListener("exchange.fanout", "queue.fanout2", result =>
{
Console.WriteLine("Message From queue.fanout2:" + result.Body);
result.Commit();
//result.RollBack();//回滚,参数表示是否重新消费
}); #endregion #region 路由模式 services.AddRabbitConsumer(options =>
{
options.Hosts = hosts;
options.Password = password;
options.Port = port;
options.UserName = userName;
options.VirtualHost = virtualHost; options.Arguments = arguments;
options.Durable = true;
options.AutoDelete = true; options.AutoAck = false;
options.FetchCount = 2;
options.Type = RabbitExchangeType.Direct;
options.RouteQueues = new RouteQueue[] { new RouteQueue() { Queue = "queue.direct1", Route = "direct1" }, new RouteQueue() { Queue = "queue.direct2", Route = "direct2" } };
}).AddListener("exchange.direct", "queue.direct1", result =>
{
Console.WriteLine("Message From queue.direct1:" + result.Body);
result.Commit();
//result.RollBack();//回滚,参数表示是否重新消费
}).AddListener("exchange.direct", "queue.direct2", result =>
{
Console.WriteLine("Message From queue.direct2:" + result.Body);
result.Commit();
//result.RollBack();//回滚,参数表示是否重新消费
}); #endregion #region 主题模式 services.AddRabbitConsumer(options =>
{
options.Hosts = hosts;
options.Password = password;
options.Port = port;
options.UserName = userName;
options.VirtualHost = virtualHost; options.Arguments = arguments;
options.Durable = true;
options.AutoDelete = true; options.FetchCount = 2;
options.AutoAck = false;
options.RouteQueues = new RouteQueue[] { new RouteQueue() { Queue = "queue.topic1", Route = "topic1.#" }, new RouteQueue() { Queue = "queue.topic2", Route = "topic2.#" } };
options.Type = RabbitExchangeType.Topic;
}).AddListener("exchange.topic", "queue.topic1", result =>
{
Console.WriteLine("Message From queue.topic1:" + result.Body);
result.Commit();
//result.RollBack();//回滚,参数表示是否重新消费
}).AddListener("exchange.topic", "queue.topic2", result =>
{
Console.WriteLine("Message From queue.topic2:" + result.Body);
result.Commit();
//result.RollBack();//回滚,参数表示是否重新消费
}); #endregion ......
}

ConfigureServices

  无论是日志的消费,还是其他五种模式的消费,都是先使用AddRabbitConsumer方法获取到一个IRabbitConsumerBuilder消费者构造对象,然后它的通过AddListener方法添加消息处理程序。

  同样的,需要注意的是,普通模式和工作模式是不基于交换机的策略模式,因此需要使用不包含交换机参数的AddListener方法:  

    #region 普通模式

    services.AddRabbitConsumer(options =>
{
options.Hosts = hosts;
options.Password = password;
options.Port = port;
options.UserName = userName;
options.VirtualHost = virtualHost; options.Arguments = arguments;
options.Durable = true;
options.AutoDelete = true; //options.FetchCount = 1;
options.AutoAck = false;
}).AddListener("queue.simple", result =>
{
Console.WriteLine("Message From queue.simple:" + result.Body);
result.Commit();
//result.RollBack();//回滚,参数表示是否重新消费
});
#endregion #region 工作模式 services.AddRabbitConsumer(options =>
{
options.Hosts = hosts;
options.Password = password;
options.Port = port;
options.UserName = userName;
options.VirtualHost = virtualHost; options.Arguments = arguments;
options.Durable = true;
options.AutoDelete = true; options.FetchCount = 2;
options.AutoAck = false;
}).AddListener("queue.worker", result =>
{
Console.WriteLine("Message From queue.worker1:" + result.Body);
result.Commit();
//result.RollBack();//回滚,参数表示是否重新消费
}).AddListener("queue.worker", result =>
{
Console.WriteLine("Message From queue.worker2:" + result.Body);
result.Commit();
//result.RollBack();//回滚,参数表示是否重新消费
});
#endregion

  而发布订阅模式、路由模式和主题模式都是基于交换机的策略模式,因此使用需要交换机参数的AddListener方法:  

    #region 发布订阅模式 

    services.AddRabbitConsumer(options =>
{
options.Hosts = hosts;
options.Password = password;
options.Port = port;
options.UserName = userName;
options.VirtualHost = virtualHost; options.Arguments = arguments;
options.Durable = true;
options.AutoDelete = true; options.FetchCount = 2;
options.AutoAck = false;
options.RouteQueues = new RouteQueue[] { new RouteQueue() { Queue = "queue.fanout1" }, new RouteQueue() { Queue = "queue.fanout2" } };
options.Type = RabbitExchangeType.Fanout;
}).AddListener("exchange.fanout", "queue.fanout1", result =>
{
Console.WriteLine("Message From queue.fanout1:" + result.Body);
result.Commit();
//result.RollBack();//回滚,参数表示是否重新消费
}).AddListener("exchange.fanout", "queue.fanout2", result =>
{
Console.WriteLine("Message From queue.fanout2:" + result.Body);
result.Commit();
//result.RollBack();//回滚,参数表示是否重新消费
}); #endregion #region 路由模式 services.AddRabbitConsumer(options =>
{
options.Hosts = hosts;
options.Password = password;
options.Port = port;
options.UserName = userName;
options.VirtualHost = virtualHost; options.Arguments = arguments;
options.Durable = true;
options.AutoDelete = true; options.AutoAck = false;
options.FetchCount = 2;
options.Type = RabbitExchangeType.Direct;
options.RouteQueues = new RouteQueue[] { new RouteQueue() { Queue = "queue.direct1", Route = "direct1" }, new RouteQueue() { Queue = "queue.direct2", Route = "direct2" } };
}).AddListener("exchange.direct", "queue.direct1", result =>
{
Console.WriteLine("Message From queue.direct1:" + result.Body);
result.Commit();
//result.RollBack();//回滚,参数表示是否重新消费
}).AddListener("exchange.direct", "queue.direct2", result =>
{
Console.WriteLine("Message From queue.direct2:" + result.Body);
result.Commit();
//result.RollBack();//回滚,参数表示是否重新消费
}); #endregion #region 主题模式 services.AddRabbitConsumer(options =>
{
options.Hosts = hosts;
options.Password = password;
options.Port = port;
options.UserName = userName;
options.VirtualHost = virtualHost; options.Arguments = arguments;
options.Durable = true;
options.AutoDelete = true; options.FetchCount = 2;
options.AutoAck = false;
options.RouteQueues = new RouteQueue[] { new RouteQueue() { Queue = "queue.topic1", Route = "topic1.#" }, new RouteQueue() { Queue = "queue.topic2", Route = "topic2.#" } };
options.Type = RabbitExchangeType.Topic;
}).AddListener("exchange.topic", "queue.topic1", result =>
{
Console.WriteLine("Message From queue.topic1:" + result.Body);
result.Commit();
//result.RollBack();//回滚,参数表示是否重新消费
}).AddListener("exchange.topic", "queue.topic2", result =>
{
Console.WriteLine("Message From queue.topic2:" + result.Body);
result.Commit();
//result.RollBack();//回滚,参数表示是否重新消费
}); #endregion

  另外,AddListener中的消息处理委托可以使用一个实现了IRabbitConsumerListener接口的类代替,如Demo中的RabbitConsumerListener:  

    public class RabbitConsumerListener : IRabbitConsumerListener
{
public Task ConsumeAsync(RecieveResult recieveResult)
{
Console.WriteLine("RabbitConsumerListener:" + recieveResult.Body);
recieveResult.Commit();
//result.RollBack();//回滚,参数表示是否重新消费
return Task.CompletedTask;
}
}

.net core使用rabbitmq消息队列 (二)的更多相关文章

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

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

  2. RabbitMQ 消息队列 二

    一:查看MQ的用户角色 rabbitmqctl list_users 二:添加新的角色,并授予权限 rabbitmqctl add_user xiaoyao 123456 rabbitmqctl se ...

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

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

  4. RabbitMQ消息队列系列教程(二)Windows下安装和部署RabbitMQ

    摘要 本篇经验将和大家介绍Windows下安装和部署RabbitMQ消息队列服务器,希望对大家的工作和学习有所帮助! 目录 一.Erlang语言环境的搭建 二.RabbitMQ服务环境的搭建 三.Ra ...

  5. RabbitMQ学习系列二:.net 环境下 C#代码使用 RabbitMQ 消息队列

    一.理论: .net环境下,C#代码调用RabbitMQ消息队列,本文用easynetq开源的.net Rabbitmq api来实现. EasyNetQ 是一个易于使用的RabbitMQ的.Net客 ...

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

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

  7. (二)RabbitMQ消息队列-RabbitMQ消息队列架构与基本概念

    原文:(二)RabbitMQ消息队列-RabbitMQ消息队列架构与基本概念 没错我还是没有讲怎么安装和写一个HelloWord,不过快了,这一章我们先了解下RabbitMQ的基本概念. Rabbit ...

  8. RabbitMQ消息队列(二)-RabbitMQ消息队列架构与基本概念

    没错我还是没有讲怎么安装和写一个HelloWord,不过快了,这一章我们先了解下RabbitMQ的基本概念. RabbitMQ架构 说是架构其实更像是应用场景下的架构(自己画的有点丑,勿嫌弃) 从图中 ...

  9. RabbitMQ基本概念(二)-RabbitMQ消息队列架构与基本概念

    没错我还是没有讲怎么安装和写一个HelloWord,不过快了,这一章我们先了解下RabbitMQ的基本概念. RabbitMQ架构 说是架构其实更像是应用场景下的架构(自己画的有点丑,勿嫌弃) 从图中 ...

随机推荐

  1. JpaRepository 增删改查

    Jpa查询 JpaRepository简单查询 基本查询也分为两种,一种是spring data默认已经实现,一种是根据查询的方法来自动解析成SQL. 预先生成方法 spring data jpa 默 ...

  2. 【划重点】Python xlwt简介和用法

    一.导入xlwt包,并初始化创建一个工作簿 import xlwt workbook=xlwt.Workbook() # 初始化创建一个工作簿 二.创建表单 sheet1=workbook.add_s ...

  3. 在项目中引入百度的ueditor编辑器

    第一步:解压ueditor压缩包 在项目中按顺序引入三个文件 <script type="text/javascript" charset="utf-8" ...

  4. Dom 解析XML

    xml文件 <?xml version="1.0" encoding="UTF-8"?><data>    <book id=&q ...

  5. 《Power Query数据清洗实战》捉虫……

    先道歉,<Power Query数据清洗实战>里,有虫-- 谢谢大家帮忙捉虫了. 谢谢法叔,他捉了四只--(汗) 112页第倒第二行,[追加查询],应是[合并查询]. 151.154.15 ...

  6. JDK ThreadPoolExecutor核心原理与实践

    一.内容概括 本文内容主要围绕JDK中的ThreadPoolExecutor展开,首先描述了ThreadPoolExecutor的构造流程以及内部状态管理的机理,随后用大量篇幅深入源码探究了Threa ...

  7. CF1166A Silent Classroom 题解

    Content 现在有 \(n\) 名学生,我们需要将这些学生分到两个班上.对于两名在同一班级的学生,如果他们的名字首字母相同,他们就会聊天. 现在给定这些学生的名字,问最少有多少对学生会在一起聊天. ...

  8. CF1095B Array Stabilization 题解

    Content 有一个长度为 \(n\) 的数组 \(a_1,a_2,a_3,...,a_n\),现在需要从这些数中删除一个数,使得 \(\max\limits_{i=1}^na_i-\min\lim ...

  9. Django的安全机制 CSRF 跨站请求访问

    跨站请求伪造 一.简介 django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成.而对于django中设置防 ...

  10. 金山云主机centos7.4根目录挂载文件书写错误无法进入系统解决办法

    由于/etc/fstab写错,根目录无法挂载,开机提示如下 处理办法: 根据提示输入root密码: 执行mount -o remount,rw /重新挂载根目录. vim 修改挂载文件 reboot重 ...