Smart.RabbitMQ
2.0.0
dotnet add package Smart.RabbitMQ --version 2.0.0
NuGet\Install-Package Smart.RabbitMQ -Version 2.0.0
<PackageReference Include="Smart.RabbitMQ" Version="2.0.0" />
<PackageVersion Include="Smart.RabbitMQ" Version="2.0.0" />
<PackageReference Include="Smart.RabbitMQ" />
paket add Smart.RabbitMQ --version 2.0.0
#r "nuget: Smart.RabbitMQ, 2.0.0"
#:package Smart.RabbitMQ@2.0.0
#addin nuget:?package=Smart.RabbitMQ&version=2.0.0
#tool nuget:?package=Smart.RabbitMQ&version=2.0.0
Smart.RabbitMQ
<a name="english"></a>
English
Smart.RabbitMQ is a high-level abstraction library built on top of RabbitMQ.Client, providing a simple, thread-safe, and feature-rich API for RabbitMQ message queue operations. It supports .NET 8, 9, and 10.
Features
- Simple API: Intuitive and easy-to-use interface for producing and consuming messages.
- Factory Pattern:
IRabbitMQFactoryfor creating producer and consumer instances. - Connection Sharing: All producers and consumers created by the same factory share a single connection, reducing resource overhead.
- Thread-Safe Internals: Connection and channel creation are guarded by a semaphore, and binding de-duplication is concurrency-safe. A single producer/consumer still owns one channel, so it should not be shared by concurrent publishers (RabbitMQ requires one channel per thread).
- Lazy Initialization: Channels are initialized on first use to avoid blocking constructors.
- Configurable Recovery:
AutomaticRecoveryEnabled,NetworkRecoveryIntervalSecondsandRequestedHeartbeatSecondsare exposed inRabbitMqOptions. - Reliable Publishing: Publisher confirms are enabled by default, messages are published as
Persistentwithcontent_type/content_encoding/message_id/timestamp, and unroutable messages can be observed via themandatoryflag plus theBasicReturnevent. - Safe Failure Handling: Deserialization failures are rejected without requeue (no poison-message loop), handler failures follow the
requeueOnFailurepolicy, and both are reported throughMessageHandleFailed. - Multiple Exchange Types: Support for Direct, Fanout, Topic, and Headers exchanges (Headers requires binding arguments, now supported by
QueueBindAsync). - Message Acknowledgment: Flexible manual and automatic acknowledgment with error handling.
- Dependency Injection: Seamless integration with Microsoft.Extensions.DependencyInjection.
- JSON Serialization: Built-in JSON serialization with camelCase naming policy (case-insensitive on read).
- Queue Binding Management: Automatic prevention of duplicate bindings.
- Configuration Validation: Built-in validation for RabbitMQ connection settings.
- Health Check:
IRabbitMQCheck.CheckAsyncprobes the broker with a short-lived dedicated connection.
Installation
Install the package via NuGet:
dotnet add package Smart.RabbitMQ
Core Components
IRabbitMQFactory
Factory interface for creating producer and consumer instances. All instances share the same connection.
public interface IRabbitMQFactory : IRabbitMQCheck, IAsyncDisposable
{
Task<SmartRabbitMQProducer> CreateProducerAsync();
Task<SmartRabbitMQConsumer<T>> CreateConsumerAsync<T>() where T : class;
Task<SmartRabbitMQConsumer> CreateConsumerAsync();
}
// Inherited from IRabbitMQCheck
Task<IConnection> CreateConnectionAsync(); // standalone connection, caller must dispose
Task<bool> CheckAsync(CancellationToken token = default); // transient probe, shared connection untouched
SmartRabbitMQProducer
Message producer with support for publishing messages to exchanges.
public class SmartRabbitMQProducer : IAsyncDisposable
{
public event AsyncEventHandler<BasicReturnEventArgs> BasicReturn;
public Task ExchangeDeclareAsync(string exchange, ExchangeType type = ExchangeType.Direct, bool durable = true, CancellationToken token = default);
public Task PublishAsync<T>(string exchange, string routingKey, T message, bool mandatory = false, CancellationToken token = default);
public Task PublishAsync(string exchange, string routingKey, string message, bool mandatory = false, CancellationToken token = default);
}
SmartRabbitMQConsumer<T>
Generic message consumer with event-driven message processing.
public class SmartRabbitMQConsumer<T> : IAsyncDisposable where T : class
{
public event AsyncMessageReceivedHandler<T> MessageReceived;
public event EventHandler<MessageErrorEventArgs<T>> MessageHandleFailed;
public Task ExchangeDeclareAsync(string exchange, ExchangeType type = ExchangeType.Direct, bool durable = true, CancellationToken token = default);
public Task<string> QueueDeclareAsync(string queue = "", bool durable = true, IDictionary<string, object?>? queueParams = null, bool exclusive = false, bool autoDelete = false, CancellationToken token = default);
public Task QueueBindAsync(string queue, string exchange, string routingKey, IDictionary<string, object?>? arguments = null, CancellationToken token = default);
public Task BasicQosAsync(ushort prefetchCount = 0, CancellationToken token = default);
public Task<string> StartConsumeAsync(bool autoAck = false, bool multiple = false, bool requeueOnFailure = true, CancellationToken token = default);
public Task CancelConsumeAsync(string consumerTag);
}
Configuration
RabbitMqOptions
Configuration options for RabbitMQ connection.
public class RabbitMqOptions
{
public string? ClientName { get; set; }
public string HostName { get; set; } = "localhost";
public int Port { get; set; } = 5672;
public string UserName { get; set; } = "guest";
public string Password { get; set; } = "guest";
public string VirtualHost { get; set; } = "/";
public bool AutomaticRecoveryEnabled { get; set; } = true; // connection auto-recovery
public int NetworkRecoveryIntervalSeconds { get; set; } = 10; // recovery retry interval
public int RequestedHeartbeatSeconds { get; set; } = 60; // 0 disables heartbeat
public bool EnablePublisherConfirms { get; set; } = true; // publish waits for broker ack
}
Usage Examples
1. Basic Producer
using Smart.RabbitMQ;
var options = new RabbitMqOptions
{
HostName = "localhost",
Port = 5672,
UserName = "guest",
Password = "guest",
VirtualHost = "/"
};
var factory = new SmartRabbitMQFactory(options);
var producer = await factory.CreateProducerAsync();
// Declare exchange
await producer.ExchangeDeclareAsync("my.exchange", ExchangeType.Direct);
// Publish message (persistent, publisher confirms enabled by default)
var message = new { Id = 1, Content = "Hello RabbitMQ" };
await producer.PublishAsync("my.exchange", "my.routing.key", message);
// Optional: observe unroutable messages instead of letting the broker drop them silently
producer.BasicReturn += (sender, args) =>
{
Console.Error.WriteLine($"Message returned: {args.ReplyText}");
return Task.CompletedTask;
};
await producer.PublishAsync("my.exchange", "my.routing.key", message, mandatory: true);
// Dispose producer (connection is managed by factory)
await producer.DisposeAsync();
// Dispose factory when done (closes shared connection)
await factory.DisposeAsync();
2. Basic Consumer
using Smart.RabbitMQ;
var options = new RabbitMqOptions
{
HostName = "localhost",
Port = 5672,
UserName = "guest",
Password = "guest",
VirtualHost = "/"
};
var factory = new SmartRabbitMQFactory(options);
var consumer = await factory.CreateConsumerAsync<MyMessage>();
// Subscribe to message event
consumer.MessageReceived += async (sender, args) =>
{
Console.WriteLine($"Received message: {args.Data?.Content}");
Console.WriteLine($"Delivery Tag: {args.DeliveryTag}");
Console.WriteLine($"Exchange: {args.Exchange}");
Console.WriteLine($"Routing Key: {args.RoutingKey}");
};
// Declare exchange
await consumer.ExchangeDeclareAsync("my.exchange", ExchangeType.Direct);
// Declare queue
var queueName = await consumer.QueueDeclareAsync("my.queue", durable: true);
// Bind queue to exchange
await consumer.QueueBindAsync(queueName, "my.exchange", "my.routing.key");
// Set QoS (prefetch count)
await consumer.BasicQosAsync(prefetchCount: 10);
// Start consuming
var consumerTag = await consumer.StartConsumeAsync(autoAck: false);
// Cancel consuming when done
await consumer.CancelConsumeAsync(consumerTag);
// Dispose consumer (connection is managed by factory)
await consumer.DisposeAsync();
// Dispose factory when done (closes shared connection)
await factory.DisposeAsync();
3. Dependency Injection Integration
using Microsoft.Extensions.DependencyInjection;
using Smart.RabbitMQ;
// Configure services
var services = new ServiceCollection();
var rabbitMQOptions = new RabbitMqOptions
{
HostName = "localhost",
Port = 5672,
UserName = "guest",
Password = "guest",
VirtualHost = "/"
};
services.AddSmartRabbitMQ(rabbitMQOptions);
// Build service provider
var serviceProvider = services.BuildServiceProvider();
// Get factory
var factory = serviceProvider.GetRequiredService<IRabbitMQFactory>();
// Create producer
var producer = await factory.CreateProducerAsync();
// Create consumer
var consumer = await factory.CreateConsumerAsync<MyMessage>();
// Or get the pre-created singletons.
// Note: only the string consumer is registered; generic consumers are created through the factory.
var producer2 = serviceProvider.GetRequiredService<SmartRabbitMQProducer>();
var stringConsumer = serviceProvider.GetRequiredService<SmartRabbitMQConsumer>();
// Health check (short-lived probe, does not touch the shared connection)
var check = serviceProvider.GetRequiredService<IRabbitMQCheck>();
bool healthy = await check.CheckAsync();
4. String Message Consumer
using Smart.RabbitMQ;
var factory = new SmartRabbitMQFactory(options);
var consumer = await factory.CreateConsumerAsync(); // String consumer
consumer.MessageReceived += async (sender, args) =>
{
Console.WriteLine($"Received string message: {args.Data}");
};
await consumer.ExchangeDeclareAsync("my.exchange");
var queueName = await consumer.QueueDeclareAsync("my.queue");
await consumer.QueueBindAsync(queueName, "my.exchange", "my.routing.key");
await consumer.StartConsumeAsync();
5. Advanced Consumer with Error Handling
using Smart.RabbitMQ;
var consumer = await factory.CreateConsumerAsync<MyMessage>();
// Acknowledge / reject is handled by the library:
// · handler completes -> BasicAck (BasicAck with multiple when multiple: true)
// · handler throws -> BasicNack(requeue: requeueOnFailure)
// · body is not JSON -> BasicNack(requeue: false), so a poison message cannot loop forever
consumer.MessageReceived += async (sender, args) =>
{
await ProcessMessageAsync(args.Data);
};
// Observe failures without interfering with the acknowledgement flow
consumer.MessageHandleFailed += (sender, e) =>
{
Console.Error.WriteLine(
$"Error processing message (deliveryTag={e.ReceivedArgs.DeliveryTag}, retriable={e.IsRetriable}): {e.Error.Message}");
};
// In production, prefer requeueOnFailure: false and configure a dead-letter exchange
await consumer.StartConsumeAsync(autoAck: false, requeueOnFailure: false);
6. Queue Parameters
using Smart.RabbitMQ;
var queueParams = new Dictionary<string, object?>
{
["x-message-ttl"] = 60000, // Message TTL: 60 seconds
["x-max-length"] = 10000, // Max queue length
["x-expires"] = 3600000, // Queue expires after 1 hour
["x-dead-letter-exchange"] = "dlx" // Dead letter exchange
};
var queueName = await consumer.QueueDeclareAsync(
queue: "my.queue",
durable: true,
queueParams: queueParams
);
7. Exchange Types
using Smart.RabbitMQ;
// Direct Exchange (Point-to-Point)
await producer.ExchangeDeclareAsync("direct.exchange", ExchangeType.Direct);
// Fanout Exchange (Broadcast)
await producer.ExchangeDeclareAsync("fanout.exchange", ExchangeType.Fanout);
// Topic Exchange (Pattern Matching)
await producer.ExchangeDeclareAsync("topic.exchange", ExchangeType.Topic);
// Headers Exchange (Header-based Routing)
await producer.ExchangeDeclareAsync("headers.exchange", ExchangeType.Headers);
// A headers binding REQUIRES arguments, otherwise nothing is ever routed
await consumer.QueueBindAsync(
queue: "my.queue",
exchange: "headers.exchange",
routingKey: string.Empty,
arguments: new Dictionary<string, object?>
{
["x-match"] = "all",
["type"] = "order"
});
Best Practices
Use Manual Acknowledgment: Set
autoAck: falsefor better control over message processing and error handling.Set Prefetch Count: Use
BasicQosAsyncto limit the number of unacknowledged messages and prevent consumer overload.
await consumer.BasicQosAsync(prefetchCount: 10);
- Dispose Resources: Dispose producer and consumer instances when done. The factory manages the shared connection.
await using var producer = await factory.CreateProducerAsync();
await using var consumer = await factory.CreateConsumerAsync<MyMessage>();
// When completely done, dispose the factory to close the connection
await factory.DisposeAsync();
Handle Exceptions: Do not rethrow inside
MessageReceived— the library already nacks for you and the rethrown exception would escape into the client's dispatch loop. SubscribeMessageHandleFailedfor logging instead.Use Durable Queues and Persistent Messages:
durable: trueonly keeps the queue definition; messages are persistent because the library publishes them withdelivery_mode=2.Configure a Dead-Letter Exchange: Add
x-dead-letter-exchangetoqueueParamsand userequeueOnFailure: falsein production, so failing messages land in the DLX instead of being redelivered forever.Validate Configuration:
AddSmartRabbitMQand theSmartRabbitMQFactoryconstructor both callRabbitMqOptions.Validate(); invalid settings throwArgumentExceptionimmediately.One Channel per Concurrent Publisher: A producer owns a single channel. For highly concurrent publishing, create one producer per concurrent unit via
CreateProducerAsync()rather than sharing a single instance across threads.
Event Arguments
MessageReceivedArgs<T>
Arguments passed to the message received event.
public class MessageReceivedArgs<T> : EventArgs
{
public string? ConsumerTag { get; init; }
public ulong DeliveryTag { get; init; }
public string? Exchange { get; init; }
public string? RoutingKey { get; init; }
public bool Redelivered { get; init; }
public T? Data { get; }
}
// Payload of MessageHandleFailed
public class MessageErrorEventArgs<T> : EventArgs
{
public Exception Error { get; }
public MessageReceivedArgs<T> ReceivedArgs { get; }
public bool IsRetriable { get; } // false => rejected without requeue (DLX candidate)
}
Project Structure
Smart.RabbitMQ/
├── SmartRabbitMQFactory.cs - Factory for creating producers and consumers
├── SmartRabbitMQProducer.cs - Message producer implementation
├── SmartRabbitMQConsumer.cs - Generic and string message consumer implementation
├── SerializeConvert.cs - JSON serialization utilities
├── RabbitMqOptions.cs - Configuration options
├── MessageReceivedArgs.cs - Event argument classes (MessageReceivedArgs / MessageErrorEventArgs)
├── ExchangeType.cs - Exchange type enumeration
├── ExchangeTypeExtensions.cs - AMQP exchange type name mapping
├── IRabbitMQFactory.cs - Factory interface
├── IRabbitMQCheck.cs - Health check contract
└── RabbitMQServiceExtensions.cs - Dependency injection extensions
Supported .NET Versions
- .NET 8
- .NET 9
- .NET 10
<a name="chinese"></a>
中文
Smart.RabbitMQ 是一个基于 RabbitMQ.Client 构建的高级抽象库,为 RabbitMQ 消息队列操作提供了简单、线程安全且功能丰富的 API。它支持 .NET 8, 9 和 10。
功能特性
- 简单易用的 API: 直观且易于使用的生产者和消费消息接口。
- 工厂模式:
IRabbitMQFactory用于创建生产者和消费者实例。 - 连接共享: 同一工厂创建的所有生产者和消费者共享同一个连接,减少资源开销。
- 线程安全: 所有操作都设计为线程安全的并发访问。
- 延迟初始化: 通道在首次使用时初始化,避免阻塞构造函数。
- 自动重连: 内置连接恢复功能,支持可配置的重试间隔。
- 多种交换机类型: 支持 Direct、Fanout、Topic 和 Headers 交换机。
- 消息确认: 灵活的手动和自动确认机制,带有错误处理。
- 依赖注入: 与 Microsoft.Extensions.DependencyInjection 无缝集成。
- JSON 序列化: 内置 JSON 序列化,使用 camelCase 命名策略。
- 队列绑定管理: 自动防止重复绑定。
- 配置验证: 内置 RabbitMQ 连接设置的验证功能。
安装
通过 NuGet 安装:
dotnet add package Smart.RabbitMQ
核心组件
IRabbitMQFactory
用于创建生产者和消费者实例的工厂接口。所有实例共享同一个连接。
public interface IRabbitMQFactory : IRabbitMQCheck, IAsyncDisposable
{
Task<SmartRabbitMQProducer> CreateProducerAsync();
Task<SmartRabbitMQConsumer<T>> CreateConsumerAsync<T>() where T : class;
Task<SmartRabbitMQConsumer> CreateConsumerAsync();
}
// 继承自 IRabbitMQCheck
Task<IConnection> CreateConnectionAsync(); // 独立连接,调用方必须自行释放
Task<bool> CheckAsync(CancellationToken token = default); // 临时探测,不影响共享连接
SmartRabbitMQProducer
消息生产者,支持向交换机发布消息。
public class SmartRabbitMQProducer : IAsyncDisposable
{
public event AsyncEventHandler<BasicReturnEventArgs> BasicReturn;
public Task ExchangeDeclareAsync(string exchange, ExchangeType type = ExchangeType.Direct, bool durable = true, CancellationToken token = default);
public Task PublishAsync<T>(string exchange, string routingKey, T message, bool mandatory = false, CancellationToken token = default);
public Task PublishAsync(string exchange, string routingKey, string message, bool mandatory = false, CancellationToken token = default);
}
SmartRabbitMQConsumer<T>
泛型消息消费者,支持事件驱动的消息处理。
public class SmartRabbitMQConsumer<T> : IAsyncDisposable where T : class
{
public event AsyncMessageReceivedHandler<T> MessageReceived;
public event EventHandler<MessageErrorEventArgs<T>> MessageHandleFailed;
public Task ExchangeDeclareAsync(string exchange, ExchangeType type = ExchangeType.Direct, bool durable = true, CancellationToken token = default);
public Task<string> QueueDeclareAsync(string queue = "", bool durable = true, IDictionary<string, object?>? queueParams = null, bool exclusive = false, bool autoDelete = false, CancellationToken token = default);
public Task QueueBindAsync(string queue, string exchange, string routingKey, IDictionary<string, object?>? arguments = null, CancellationToken token = default);
public Task BasicQosAsync(ushort prefetchCount = 0, CancellationToken token = default);
public Task<string> StartConsumeAsync(bool autoAck = false, bool multiple = false, bool requeueOnFailure = true, CancellationToken token = default);
public Task CancelConsumeAsync(string consumerTag);
}
配置
RabbitMqOptions
RabbitMQ 连接配置选项。
public class RabbitMqOptions
{
public string? ClientName { get; set; }
public string HostName { get; set; } = "localhost";
public int Port { get; set; } = 5672;
public string UserName { get; set; } = "guest";
public string Password { get; set; } = "guest";
public string VirtualHost { get; set; } = "/";
public bool AutomaticRecoveryEnabled { get; set; } = true; // connection auto-recovery
public int NetworkRecoveryIntervalSeconds { get; set; } = 10; // recovery retry interval
public int RequestedHeartbeatSeconds { get; set; } = 60; // 0 disables heartbeat
public bool EnablePublisherConfirms { get; set; } = true; // publish waits for broker ack
}
使用示例
1. 基础生产者
using Smart.RabbitMQ;
var options = new RabbitMqOptions
{
HostName = "localhost",
Port = 5672,
UserName = "guest",
Password = "guest",
VirtualHost = "/"
};
var factory = new SmartRabbitMQFactory(options);
var producer = await factory.CreateProducerAsync();
// 声明交换机
await producer.ExchangeDeclareAsync("my.exchange", ExchangeType.Direct);
// 发布消息(默认持久化并启用发布者确认)
var message = new { Id = 1, Content = "Hello RabbitMQ" };
await producer.PublishAsync("my.exchange", "my.routing.key", message);
// 可选:感知无法路由的消息,而不是让 Broker 静默丢弃
producer.BasicReturn += (sender, args) =>
{
Console.Error.WriteLine($"消息被退回:{args.ReplyText}");
return Task.CompletedTask;
};
await producer.PublishAsync("my.exchange", "my.routing.key", message, mandatory: true);
// 释放生产者(连接由工厂管理)
await producer.DisposeAsync();
// 完成后释放工厂(关闭共享连接)
await factory.DisposeAsync();
2. 基础消费者
using Smart.RabbitMQ;
var options = new RabbitMqOptions
{
HostName = "localhost",
Port = 5672,
UserName = "guest",
Password = "guest",
VirtualHost = "/"
};
var factory = new SmartRabbitMQFactory(options);
var consumer = await factory.CreateConsumerAsync<MyMessage>();
// 订阅消息事件
consumer.MessageReceived += async (sender, args) =>
{
Console.WriteLine($"收到消息: {args.Data?.Content}");
Console.WriteLine($"投递标签: {args.DeliveryTag}");
Console.WriteLine($"交换机: {args.Exchange}");
Console.WriteLine($"路由键: {args.RoutingKey}");
};
// 声明交换机
await consumer.ExchangeDeclareAsync("my.exchange", ExchangeType.Direct);
// 声明队列
var queueName = await consumer.QueueDeclareAsync("my.queue", durable: true);
// 绑定队列到交换机
await consumer.QueueBindAsync(queueName, "my.exchange", "my.routing.key");
// 设置 QoS(预取计数)
await consumer.BasicQosAsync(prefetchCount: 10);
// 开始消费
var consumerTag = await consumer.StartConsumeAsync(autoAck: false);
// 完成后取消消费
await consumer.CancelConsumeAsync(consumerTag);
// 释放消费者(连接由工厂管理)
await consumer.DisposeAsync();
// 完成后释放工厂(关闭共享连接)
await factory.DisposeAsync();
3. 依赖注入集成
using Microsoft.Extensions.DependencyInjection;
using Smart.RabbitMQ;
// 配置服务
var services = new ServiceCollection();
var rabbitMQOptions = new RabbitMqOptions
{
HostName = "localhost",
Port = 5672,
UserName = "guest",
Password = "guest",
VirtualHost = "/"
};
services.AddSmartRabbitMQ(rabbitMQOptions);
// 构建服务提供者
var serviceProvider = services.BuildServiceProvider();
// 获取工厂
var factory = serviceProvider.GetRequiredService<IRabbitMQFactory>();
// 创建生产者
var producer = await factory.CreateProducerAsync();
// 创建消费者
var consumer = await factory.CreateConsumerAsync<MyMessage>();
// 或者直接获取预先创建的单例。
// 注意:容器中只注册了字符串消费者,泛型消费者需通过工厂创建
var producer2 = serviceProvider.GetRequiredService<SmartRabbitMQProducer>();
var stringConsumer = serviceProvider.GetRequiredService<SmartRabbitMQConsumer>();
// 健康检查(临时探测,不影响共享连接)
var check = serviceProvider.GetRequiredService<IRabbitMQCheck>();
bool healthy = await check.CheckAsync();
4. 字符串消息消费者
using Smart.RabbitMQ;
var factory = new SmartRabbitMQFactory(options);
var consumer = await factory.CreateConsumerAsync(); // 字符串消费者
consumer.MessageReceived += async (sender, args) =>
{
Console.WriteLine($"收到字符串消息: {args.Data}");
};
await consumer.ExchangeDeclareAsync("my.exchange");
var queueName = await consumer.QueueDeclareAsync("my.queue");
await consumer.QueueBindAsync(queueName, "my.exchange", "my.routing.key");
await consumer.StartConsumeAsync();
5. 高级消费者与错误处理
using Smart.RabbitMQ;
var consumer = await factory.CreateConsumerAsync<MyMessage>();
// 确认/拒绝由库内部完成:
// · 处理器正常返回 -> BasicAck(multiple 为 true 时批量确认)
// · 处理器抛出异常 -> BasicNack(requeue: requeueOnFailure)
// · 消息体不是合法JSON -> BasicNack(requeue: false),因此不会出现毒消息无限重投
consumer.MessageReceived += async (sender, args) =>
{
await ProcessMessageAsync(args.Data);
};
// 观测失败,且不影响确认流程
consumer.MessageHandleFailed += (sender, e) =>
{
Console.Error.WriteLine(
$"消息处理失败(deliveryTag={e.ReceivedArgs.DeliveryTag},是否重新入队={e.IsRetriable}):{e.Error.Message}");
};
// 生产环境建议 requeueOnFailure: false,并配合死信交换机使用
await consumer.StartConsumeAsync(autoAck: false, requeueOnFailure: false);
6. 队列参数
using Smart.RabbitMQ;
var queueParams = new Dictionary<string, object?>
{
["x-message-ttl"] = 60000, // 消息 TTL: 60 秒
["x-max-length"] = 10000, // 队列最大长度
["x-expires"] = 3600000, // 队列在 1 小时后过期
["x-dead-letter-exchange"] = "dlx" // 死信交换机
};
var queueName = await consumer.QueueDeclareAsync(
queue: "my.queue",
durable: true,
queueParams: queueParams
);
7. 交换机类型
using Smart.RabbitMQ;
// 直连交换机(点对点)
await producer.ExchangeDeclareAsync("direct.exchange", ExchangeType.Direct);
// 扇形交换机(广播)
await producer.ExchangeDeclareAsync("fanout.exchange", ExchangeType.Fanout);
// 主题交换机(模式匹配)
await producer.ExchangeDeclareAsync("topic.exchange", ExchangeType.Topic);
// 头交换机(基于头的路由)
await producer.ExchangeDeclareAsync("headers.exchange", ExchangeType.Headers);
// 头交换机的绑定必须提供 arguments,否则消息永远不会被路由
await consumer.QueueBindAsync(
queue: "my.queue",
exchange: "headers.exchange",
routingKey: string.Empty,
arguments: new Dictionary<string, object?>
{
["x-match"] = "all",
["type"] = "order"
});
最佳实践
使用手动确认: 设置
autoAck: false以更好地控制消息处理和错误处理。设置预取计数: 使用
BasicQosAsync限制未确认消息的数量,防止消费者过载。
await consumer.BasicQosAsync(prefetchCount: 10);
- 释放资源: 使用完毕后释放生产者和消费者实例。工厂管理共享连接。
await using var producer = await factory.CreateProducerAsync();
await using var consumer = await factory.CreateConsumerAsync<MyMessage>();
// 完全完成后,释放工厂以关闭连接
await factory.DisposeAsync();
处理异常: 不要在
MessageReceived中重新抛出异常——库已经完成了拒绝(Nack),再抛出只会让异常逃逸到客户端的投递分发循环。需要记录日志时请订阅MessageHandleFailed。同时使用持久化队列与持久化消息:
durable: true只保证队列定义存活;消息之所以持久化,是因为库在发布时设置了delivery_mode=2。配置死信交换机: 在
queueParams中加入x-dead-letter-exchange,并在生产环境使用requeueOnFailure: false,让处理失败的消息进入死信队列,而不是被无限重投。校验配置:
AddSmartRabbitMQ与SmartRabbitMQFactory构造函数都会调用RabbitMqOptions.Validate(),非法配置会立即抛出ArgumentException。并发发布时不要共享生产者: 一个生产者只持有一个通道。高并发发布场景请通过
CreateProducerAsync()为每个并发单元创建独立生产者,而不是多线程共享同一实例。
事件参数
MessageReceivedArgs<T>
传递给消息接收事件的参数。
public class MessageReceivedArgs<T> : EventArgs
{
public string? ConsumerTag { get; init; }
public ulong DeliveryTag { get; init; }
public string? Exchange { get; init; }
public string? RoutingKey { get; init; }
public bool Redelivered { get; init; }
public T? Data { get; }
}
// Payload of MessageHandleFailed
public class MessageErrorEventArgs<T> : EventArgs
{
public Exception Error { get; }
public MessageReceivedArgs<T> ReceivedArgs { get; }
public bool IsRetriable { get; } // false => rejected without requeue (DLX candidate)
}
项目结构
Smart.RabbitMQ/
├── SmartRabbitMQFactory.cs - 用于创建生产者和消费者的工厂
├── SmartRabbitMQProducer.cs - 消息生产者实现
├── SmartRabbitMQConsumer.cs - 泛型与字符串消息消费者实现
├── SerializeConvert.cs - JSON 序列化工具
├── RabbitMqOptions.cs - 配置选项
├── MessageReceivedArgs.cs - 事件参数类(MessageReceivedArgs / MessageErrorEventArgs)
├── ExchangeType.cs - 交换机类型枚举
├── ExchangeTypeExtensions.cs - AMQP 交换机类型名称映射
├── IRabbitMQFactory.cs - 工厂接口
├── IRabbitMQCheck.cs - 健康检查契约
└── RabbitMQServiceExtensions.cs - 依赖注入扩展
支持的 .NET 版本
- .NET 8
- .NET 9
- .NET 10
Developed by zenglei
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Microsoft.Extensions.DependencyInjection (>= 10.0.8)
- RabbitMQ.Client (>= 7.2.1)
-
net8.0
- Microsoft.Extensions.DependencyInjection (>= 10.0.8)
- RabbitMQ.Client (>= 7.2.1)
-
net9.0
- Microsoft.Extensions.DependencyInjection (>= 10.0.8)
- RabbitMQ.Client (>= 7.2.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.0.0 | 81 | 10/19/2026 |
| 1.1.2 | 152 | 5/16/2026 |
| 1.1.1 | 140 | 3/19/2026 |
| 1.1.0 | 140 | 2/17/2026 |
| 1.0.0 | 140 | 2/14/2026 |
| 1.0.0-beta.14 | 99 | 2/11/2026 |
| 1.0.0-beta.13 | 97 | 2/10/2026 |
| 1.0.0-beta.12 | 106 | 12/30/2025 |
| 1.0.0-beta.11 | 177 | 4/5/2025 |
| 1.0.0-beta.10 | 230 | 3/20/2025 |
| 1.0.0-beta.9 | 238 | 3/17/2025 |
| 1.0.0-beta.8 | 209 | 3/16/2025 |
| 1.0.0-beta.7 | 212 | 3/16/2025 |
| 1.0.0-beta.6 | 214 | 3/16/2025 |
| 1.0.0-beta.5 | 212 | 3/16/2025 |
| 1.0.0-beta.4 | 255 | 3/4/2025 |
| 1.0.0-beta.3 | 261 | 3/4/2025 |
| 1.0.0-beta.2 | 267 | 3/3/2025 |
| 1.0.0-beta.1 | 189 | 3/2/2025 |