在 ASP.NET Core 中发布 RabbitMQ 消息

介绍

前几天写了一篇文章,介绍如何在ASP.NET Core中通过后台服务消费RabbitMQ消息。在本文中,您将学习如何发布 RabbitMQ 消息。

运行 RabbitMQ 服务

如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。

RabbitMQ 设置

在appsettings.json 中添加 RabbitMQ 的配置

{

"Logging": {

"LogLevel": {

"Default": "Warning"

}

},

"AllowedHosts": "*",

"rabbit": {

"UserName": "guest",

"Password": "guest",

"HostName": "localhost",

"VHost": "/",

"Port": 5672

}

}

创建一个映射appsettings.json 中的rabbit部分的类

public class RabbitOptions

{

public string UserName { get; set; }

public string Password { get; set; }

public string HostName { get; set; }

public int Port { get; set; } = 5672;

public string VHost { get; set; } = "/";

}

重用 RabbitMQ 连接的通道

为什么要重用渠道?

根据官方的.NET/C# 客户端 API 指南文档,我们可以考虑重用通道,因为这些通道是长期存在的,但由于许多可恢复的协议错误将导致通道关闭,因此每次操作关闭和打开新通道通常是不必要的。

这里,我们将使用对象池来完成这个工作!微软提供了一个名为Microsoft.Extensions.ObjectPool的包 可以帮助我们简化一些工作。

在使用对象池之前,我们首先需要声明通道的策略。这里我们创建一个名为RabbitModelPooledObjectPolicy的类 ,并实现 IPooledObjectPolicy<IModel>接口。

using Microsoft.Extensions.ObjectPool;

using Microsoft.Extensions.Options;

using RabbitMQ.Client;

public class RabbitModelPooledObjectPolicy : IPooledObjectPolicy<IModel>

{

private readonly RabbitOptions _options;

private readonly IConnection _connection;

public RabbitModelPooledObjectPolicy(IOptions<RabbitOptions> optionsAccs)

{

_options = optionsAccs.Value;

_connection = GetConnection();

}

private IConnection GetConnection()

{

var factory = new ConnectionFactory()

{

HostName = _options.HostName,

UserName = _options.UserName,

Password = _options.Password,

Port = _options.Port,

VirtualHost = _options.VHost,

};

return factory.CreateConnection();

}

public IModel Create()

{

return _connection.CreateModel();

}

public bool Return(IModel obj)

{

if (obj.IsOpen)

{

return true;

}

else

{

obj?.Dispose();

return false;

}

}

}

其中有两个重要的方法,一个是Create,另一个是Return。

Create 方法告诉池如何创建通道对象。

Return方法告诉池,如果通道对象仍然处于可以使用的状态,我们应该将其返回到池中;否则,我们下次不应该使用它。

RabbitMQ 管理器

我们创建一个管理接口来处理发布方法。

public interface IRabbitManager

{

void Publish<T>(T message, string exchangeName, string exchangeType, string routeKey)

where T : class;

}

下面的代码演示了它的一个实现类。

public class RabbitManager : IRabbitManager

{

private readonly DefaultObjectPool<IModel> _objectPool;

public RabbitManager(IPooledObjectPolicy<IModel> objectPolicy)

{

_objectPool = new DefaultObjectPool<IModel>(objectPolicy, Environment.ProcessorCount * 2);

}

public void Publish<T>(T message, string exchangeName, string exchangeType, string routeKey)

where T : class

{

if (message == null)

return;

var channel = _objectPool.Get();

try

{

channel.ExchangeDeclare(exchangeName, exchangeType, true, false, null);

var sendBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(message));

var properties = channel.CreateBasicProperties();

properties.Persistent = true;

channel.BasicPublish(exchangeName, routeKey, properties, sendBytes);

}

catch (Exception ex)

{

throw ex;

}

finally

{

_objectPool.Return(channel);

}

}

}

我们在构造函数中创建了一个对象池。在向 RabbitMQ 发布消息之前,我们需要从对象池中获取一个通道,然后构造有效负载。

发布后,无论发布成功还是失败,我们都应该将此通道对象返回到对象池中。

RabbitMQ 扩展

创建扩展方法来简化注册。

public static class RabbitServiceCollectionExtensions

{

public static IServiceCollection AddRabbit(this IServiceCollection services, IConfiguration configuration)

{

var rabbitConfig = configuration.GetSection("rabbit");

services.Configure<RabbitOptions>(rabbitConfig);

services.AddSingleton<ObjectPoolProvider, DefaultObjectPoolProvider>();

services.AddSingleton<IPooledObjectPolicy<IModel>, RabbitModelPooledObjectPolicy>();

services.AddSingleton<IRabbitManager, RabbitManager>();

return services;

}

}

转到启动类 Startup.cs。

public void ConfigureServices(IServiceCollection services)

{

services.AddRabbit(Configuration);

services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

}

RabbitMQ Manager 的使用

我们在ValuesController中添加一些代码 。

Route("api/\[controller\]")

ApiController

public class ValuesController : ControllerBase

{

private IRabbitManager _manager;

public ValuesController(IRabbitManager manager)

{

_manager = manager;

}

// GET api/values

HttpGet

public ActionResult<IEnumerable<string>> Get()

{

// other opreation

// if above operation succeed, publish a message to RabbitMQ

var num = new System.Random().Next(9000);

// publish message

_manager.Publish(new

{

field1 = $"Hello-{num}",

field2 = $"rabbit-{num}"

}, "demo.exchange.topic.dotnetcore", "topic", "*.queue.durable.dotnetcore.#");

return new string[] { "value1", "value2" };

}

}

这里我们将创建一个名为demo.exchange.topic.dotnetcore的主题类型交换,它还将消息发送到绑定名为*.queue.durable.dotnetcore.#的路由键的队列。

笔记
队列中的一条消息只会被一个消费者消费。

结果

为了演示,我们创建一个队列并将其绑定到路由键,而不是创建消费者。

发布消息后,我们可以查看消息是否准备好。

我们可以使用GetMessage按钮来检查消息。

概括

本文介绍了如何在 ASP.NET Core 中发布 RabbitMQ 消息。希望对您有所帮助!

如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。

相关推荐
creator_Li4 小时前
RabbitMQ示例
rabbitmq
惊讶的猫5 小时前
rabbitmq实践小案例
分布式·rabbitmq
AC赳赳老秦6 小时前
代码生成超越 GPT-4:DeepSeek-V4 编程任务实战与 2026 开发者效率提升指南
数据库·数据仓库·人工智能·科技·rabbitmq·memcache·deepseek
惊讶的猫8 小时前
rabbitmq初步介绍
分布式·rabbitmq
惊讶的猫10 小时前
AMQP 与 RabbitMQ 四大模型
分布式·rabbitmq
像少年啦飞驰点、11 小时前
从零开始学 RabbitMQ:小白也能懂的消息队列实战指南
java·spring boot·微服务·消息队列·rabbitmq·异步编程
lekami_兰12 小时前
RabbitMQ 延迟队列实现指南:两种方案手把手教你搞定
后端·rabbitmq·延迟队列
为什么不问问神奇的海螺呢丶1 天前
n9e categraf rabbitmq监控配置
分布式·rabbitmq·ruby
m0_687399841 天前
telnet localhost 15672 RabbitMQ “Connection refused“ 错误表示目标主机拒绝了连接请求。
分布式·rabbitmq
Ronin3051 天前
日志打印和实用 Helper 工具
数据库·sqlite·rabbitmq·文件操作·uuid生成