.net Rabbitmq 封装 包含 直连交换机 死信队列(十一)
Connector 文件夹 代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | public interface IConnectors : IDisposable { /// <summary> /// 初始化交换机队列 /// </summary> /// <param name="definition"></param> /// <returns></returns> Task InitExchangeAndQueueAsync(ExchangeAndQueueDefinition definition); /// <summary> /// 获取缓存中的key 将已经初始化的交换机队列的信道IChannel存入 /// 缓存中提高性能 /// </summary> /// <param name="definition">交换机队列的声明对象</param> /// <returns></returns> string GetMemoryCacheKey(ExchangeAndQueueDefinition definition); /// <summary> /// 信道 /// </summary> IChannel Channel { get ; } } |
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | using Microsoft.Extensions.Options; using RabbitCustorm.Message; using RabbitCustorm.RabbitMQExtends; using RabbitMQ.Client; using System; using System.Collections.Generic; using System.Diagnostics.Metrics; using System.Linq; using System.Reflection.Metadata.Ecma335; using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; namespace RabbitCustorm.Connection.Connectors { /// <summary> /// 此类需要单例模式 /// </summary> public class Connectors : IConnectors { private IConnection conn; private IChannel channel; private ConnectionFactory factory; private readonly RabbitOptions rabbitOptions; public Connectors(IOptions<RabbitOptions> rabbitOptions) { this .rabbitOptions = rabbitOptions.Value; //初始化 Init(); } /// <summary> /// 初始化 /// </summary> private void Init() { factory = new ConnectionFactory() { UserName = rabbitOptions.UserName, Password = rabbitOptions.Password, VirtualHost = rabbitOptions.VirtualHost, HostName = rabbitOptions.HostName, Port = rabbitOptions.Port, DispatchConsumersAsync = true //开启异步消费者 }; this .conn = factory.CreateConnection(); this .channel = conn.CreateChannel(); } /// <summary> /// 信道 /// </summary> public IChannel Channel => this .channel; /// <summary> /// 初始化 交换机 /// </summary> /// <param name="definition"></param> /// <returns></returns> public async Task InitExchangeAndQueueAsync(ExchangeAndQueueDefinition definition) { if (! this .channel.IsOpen) { throw new Exception( "信道(channel)未开启!!!" ); } //如果包含 死信 定义 if (definition.Arguments != null && definition.Arguments.Keys.Contains( "x-dead-letter-exchange" )) { //死信交换机 string deadLetterExchange = definition.Arguments[ "x-dead-letter-exchange" ].ToString(); //死信队列 string deadLetterQueue = definition.Arguments[ "x-dead-letter-queue" ].ToString(); //死信路由key string deadletterRoutingKey = definition.Arguments[ "x-dead-letter-routing-key" ].ToString(); await channel.ExchangeDeclareAsync(exchange: deadLetterExchange, type: ExchangeType.Direct, passive: false , durable: true , autoDelete: false , arguments: null ); await channel.QueueDeclareAsync(queue: deadLetterQueue, passive: false , durable: true , exclusive: false , autoDelete: false , arguments: null ); await channel.QueueBindAsync(queue: deadLetterQueue, exchange: deadLetterExchange, routingKey: deadletterRoutingKey, arguments: null ); } await channel.ExchangeDeclareAsync(exchange: definition.ExchangeName, type: ExchangeType.Direct, passive: false , durable: true , autoDelete: false , arguments: definition.Arguments); await channel.QueueDeclareAsync(queue: definition.QueueName, passive: false , durable: true , exclusive: false , autoDelete: false , arguments: definition.Arguments); await channel.QueueBindAsync(queue: definition.QueueName, exchange: definition.ExchangeName, routingKey: definition.RouteKey, arguments: definition.Arguments); } /// <summary> /// 获取 MemoryCache Key /// </summary> /// <param name="definition"></param> /// <returns></returns> public string GetMemoryCacheKey(ExchangeAndQueueDefinition definition) { string key = $ "{definition.ExchangeName}_{definition.QueueName}_{definition.RouteKey}" ; //如果是死信队列 if (definition.Arguments != null && definition.Arguments.ContainsKey( "x-dead-letter-exchange" )) { //死信交换机 string deadLetterExchange = definition.Arguments[ "x-dead-letter-exchange" ].ToString(); //死信队列 string deadLetterQueue = definition.Arguments[ "x-dead-letter-queue" ].ToString(); //死信路由key string deadletterRoutingKey = definition.Arguments[ "x-dead-letter-routing-key" ].ToString(); return key += $ "{deadLetterExchange}_{deadLetterQueue}_{deadletterRoutingKey}" ; } return $ "{definition.ExchangeName}_{definition.QueueName}_{definition.RouteKey}" ; } public async void Dispose() { if (conn != null ) { await conn.CloseAsync(); } if (channel != null ) { await channel.CloseAsync(); } } } } |
Consumer 文件夹代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | using RabbitCustorm.Message; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace RabbitCustorm { /// <summary> /// 消费者接口 /// </summary> public interface IConsumer { /// <summary> /// 接收消息 /// </summary> /// <param name="definition"><交换机队列声明/param> /// <param name="func">消息处理委托,返回是否处理成功</param> void Received(ExchangeAndQueueDefinition definition, Func< string , bool > func); } } |
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using RabbitCustorm.Connection.Connectors; using RabbitCustorm.Message; using RabbitMQ.Client; using RabbitMQ.Client.Events; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Channels; using System.Threading.Tasks; namespace RabbitCustorm { /// <summary> /// 消费者 /// </summary> public class Consumer : IConsumer { private readonly IConnectors connectors; private readonly ILogger<Producer> logger; private readonly IMemoryCache memoryCache; public Consumer(IConnectors connectors, ILogger<Producer> logger, IMemoryCache memoryCache) { this .connectors = connectors; this .logger = logger; this .memoryCache = memoryCache; } /// <summary> /// 接收消息 /// </summary> /// <param name="definition">交换机和队列定义</param> /// <param name="func">消息处理函数</param> public async void Received(ExchangeAndQueueDefinition definition, Func< string , bool > func) { //获取 memoryCache Key string memoryCacheKey = this .connectors.GetMemoryCacheKey(definition); //判断 内存缓存中是否存在 channel 如果不存在 就存进去 if (! this .memoryCache.TryGetValue<IChannel>(memoryCacheKey, out IChannel channel)) { //初始化交换机 await this .connectors.InitExchangeAndQueueAsync(definition); channel = this .connectors.Channel; this .memoryCache.Set<IChannel>(memoryCacheKey, channel); } //var consumer = new EventingBasicConsumer(channel); //异步消费 var consumer = new AsyncEventingBasicConsumer(channel); consumer.Received += async (ch, ea) => { // channel.BasicQos(0, 1, false); string str = Encoding.UTF8.GetString(ea.Body.ToArray(), 0, ea.Body.Length); if (func(str)) { //应答 await channel.BasicAckAsync(ea.DeliveryTag, false ); } else { //拒绝消息 await channel.BasicRejectAsync(ea.DeliveryTag, false ); } }; string consumerTag = this .connectors.Channel.BasicConsume(definition.QueueName, false , consumer); } } } |
Message 文件夹 代码
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 32 33 | using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace RabbitCustorm.Message { /// <summary> /// 交换机 队列 定义 /// </summary> public class ExchangeAndQueueDefinition { /// <summary> /// 交换机名称 /// </summary> public string ExchangeName { get ; set ; } /// <summary> /// 队列名称 /// </summary> public string QueueName { get ; set ; } /// <summary> /// 路由key /// </summary> public string RouteKey { get ; set ; } /// <summary> /// 参数 /// </summary> public Dictionary< string , object > Arguments { get ; set ; } = null ; } } |
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace RabbitCustorm.Message { /// <summary> /// 声明 交换机名称 队列名称 便于复用 /// </summary> public static class ExchangeAndQueueStatement { public static readonly object lockProducer = new object (); #region 交换机类型 direct 的交换机和队列声明 public const string TestDirectExchange = "TestDirectExchange" ; public const string TestDirectQueue = "TestDirectQueue" ; public const string TestDirectKey = "TestDirectKey" ; #endregion #region 死信交换机和队列,routekey声明 /// <summary> /// 死信交换机 /// </summary> public const string ExchangeDeadLetter = "ExchangeDeadLetter" ; /// <summary> /// 死信队列 /// </summary> public const string QueueDeadLetter = "QueueDeadLetter" ; /// <summary> /// 死信route key /// </summary> public const string RouteDeadLetter = "RouteDeadLetter" ; /// <summary> /// 死信中 正常交换机 /// </summary> public const string TestExchange = "TestExchange" ; /// <summary> /// 死信中 正常队列 /// </summary> public const string TestQueue = "TestQueue" ; /// <summary> /// 死信中 正常路由Key /// </summary> public const string TestKey = "TestKey" ; #endregion } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace RabbitCustorm.Message { /// <summary> /// 消息传输类 /// </summary> public class MessageTrans { /// <summary> /// 交换机 队列 定义 /// </summary> public ExchangeAndQueueDefinition Definition { get ; set ; } /// <summary> /// 消息体 /// </summary> public object Body { get ; set ; } } } |
Producer 文件夹代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | using RabbitCustorm.Message; using RabbitMQ.Client; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace RabbitCustorm { /// <summary> /// 生产者接口 /// </summary> public interface IProducer { /// <summary> /// 发消息 /// </summary> /// <param name="message">消息传输对象</param> /// <returns></returns> Task SendMessageAsync(MessageTrans message); } } |
using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using RabbitCustorm.Connection.Connectors; using RabbitCustorm.Message; using RabbitMQ.Client; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.Json.Serialization; using System.Threading; using System.Threading.Tasks; namespace RabbitCustorm { /// <summary> /// exchange direct 直连 类型 /// </summary> public class Producer : IProducer { private readonly IConnectors connectors; private readonly ILogger<Producer> logger; private readonly IMemoryCache memoryCache; public Producer(IConnectors connectors, ILogger<Producer> logger, IMemoryCache memoryCache) { this.connectors = connectors; this.logger = logger; this.memoryCache = memoryCache; } public async Task SendMessageAsync(MessageTrans message) { try { //获取 memoryCache key string memoryCacheKey = connectors.GetMemoryCacheKey(message.Definition); //判断 内存缓存中是否存在 channel 如果不存在 就存进去 if (!memoryCache.TryGetValue(memoryCacheKey, out IChannel channel)) { //初始化交换机 await connectors.InitExchangeAndQueueAsync(message.Definition); channel = connectors.Channel; memoryCache.Set(memoryCacheKey, channel); } //发送消息 string body = JsonConvert.SerializeObject(message.Body); byte[] messageBodyBytes = Encoding.UTF8.GetBytes(body); //开启事务 await connectors.Channel.TxSelectAsync(); await channel.BasicPublishAsync(message.Definition.ExchangeName, message.Definition.RouteKey, messageBodyBytes); //事务提交 await connectors.Channel.TxCommitAsync(); logger.LogInformation($"发送消息{body}"); } catch (Exception ex) { //事务回滚 await connectors.Channel.TxRollbackAsync(); logger.LogError($"发送消息失败{ex.Message}", ex); } } } }
RabbitMQExtends 文件夹代码
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 32 33 34 35 | using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace RabbitCustorm.RabbitMQExtends { /// <summary> /// rabbit 配置类 /// </summary> public class RabbitOptions { /// <summary> /// 用户名 /// </summary> public string UserName { get ; set ; } /// <summary> /// 密码 /// </summary> public string Password { get ; set ; } /// <summary> /// 虚拟机主机 例如 center /// </summary> public string VirtualHost { get ; set ; } /// <summary> /// rabbitmq 主机 例如 192.168.0.168 /// </summary> public string HostName { get ; set ; } /// <summary> /// 端口号 5672 /// </summary> public int Port { get ; set ; } = 5672; } } |
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using RabbitCustorm.Connection.Connectors; using RabbitCustorm; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace RabbitCustorm.RabbitMQExtends { public static class RabbitMQExtend { /// <summary> /// 添加 生产者 和 消费者 /// </summary> /// <param name="services"></param> /// <param name="config"></param> /// <returns></returns> public static IServiceCollection AddRabbitMQ( this IServiceCollection services, IConfiguration config) { services.Configure<RabbitOptions>(config.GetSection( "RabbitOptions" )); //增加内从缓存注入 services.AddMemoryCache(); services.AddSingleton<IConnectors, Connectors>(); services.AddScoped<IProducer, Producer>(); services.AddScoped<IConsumer, Consumer>(); return services; } /// <summary> /// 添加 rabbit 只有 生产者 /// </summary> /// <param name="services"></param> /// <param name="config"></param> /// <returns></returns> public static IServiceCollection AddRabbitMQProducer( this IServiceCollection services, IConfiguration config) { services.Configure<RabbitOptions>(config.GetSection( "RabbitOptions" )); //增加内从缓存注入 services.AddMemoryCache(); services.AddSingleton<IConnectors, Connectors>(); services.AddScoped<IProducer, Producer>(); return services; } /// <summary> /// 添加 rabbit 只有 消费者 /// </summary> /// <param name="services"></param> /// <param name="config"></param> /// <returns></returns> public static IServiceCollection AddRabbitMQConsumer( this IServiceCollection services, IConfiguration config) { services.Configure<RabbitOptions>(config.GetSection( "RabbitOptions" )); //增加内从缓存注入 services.AddMemoryCache(); services.AddSingleton<IConnectors, Connectors>(); services.AddScoped<IConsumer, Consumer>(); return services; } } } |
以上是rabbitmq 封装类库代码
下面 是测试webapi
appsettings.json
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | { "Logging" : { "LogLevel" : { "Default" : "Information" , "Microsoft.AspNetCore" : "Warning" } }, "AllowedHosts" : "*" , "RabbitOptions" : { "HostName" : "192.168.0.168" , "Port" : "5672" , "UserName" : "test" , "Password" : "test" , "VirtualHost" : "center" } } |
Program.cs
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 32 | using RabbitCustorm.RabbitMQExtends; using RabbitMqWebAPI; using System.Runtime.CompilerServices; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); builder.Services.AddRabbitMQ(builder.Configuration); //测试直连交换机 builder.Services.AddHostedService<TestDirectService>(); //测试私信队列交换机 builder.Services.AddHostedService<TestDeadLetterService>(); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run(); |
TestDeadLetterService
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 32 33 34 35 36 37 38 39 40 41 42 | using Microsoft.Extensions.Hosting; using Microsoft.OpenApi.Writers; using RabbitCustorm; using RabbitCustorm.Message; using RabbitMqWebAPI.Controllers; namespace RabbitMqWebAPI { /// <summary> /// 测试私信队列 /// </summary> public class TestDeadLetterService : BackgroundService { private readonly ILogger<RabbitConsumerController> logger; private readonly IServiceScopeFactory scopeFactory; public TestDeadLetterService(ILogger<RabbitConsumerController> logger, IServiceScopeFactory scopeFactory) { this .logger = logger; this .scopeFactory = scopeFactory; } protected override Task ExecuteAsync(CancellationToken stoppingToken) { using IServiceScope scope = this .scopeFactory.CreateScope(); IConsumer consumer = scope.ServiceProvider.GetRequiredService<IConsumer>(); Task.Factory.StartNew(() => { consumer.Received( new ExchangeAndQueueDefinition { ExchangeName = ExchangeAndQueueStatement.ExchangeDeadLetter, QueueName = ExchangeAndQueueStatement.QueueDeadLetter, RouteKey = ExchangeAndQueueStatement.RouteDeadLetter, }, body => { this .logger.LogInformation($ "收到死信消息{body}" ); return true ; }); }, TaskCreationOptions.LongRunning); return Task.CompletedTask; } } } |
TestDirectService
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | using RabbitCustorm; using RabbitCustorm.Message; using RabbitMqWebAPI.Controllers; namespace RabbitMqWebAPI { /// <summary> /// 测试直连交换机 /// </summary> public class TestDirectService : IHostedService { private readonly ILogger<RabbitConsumerController> logger; private readonly IServiceScopeFactory scopeFactory; public TestDirectService(ILogger<RabbitConsumerController> logger, IServiceScopeFactory scopeFactory) { this .logger = logger; this .scopeFactory = scopeFactory; } public Task StartAsync(CancellationToken cancellationToken) { using AsyncServiceScope asyncService = scopeFactory.CreateAsyncScope(); IConsumer consumer = asyncService.ServiceProvider.GetRequiredService<IConsumer>(); Task.Factory.StartNew(() => { consumer.Received( new ExchangeAndQueueDefinition { ExchangeName = ExchangeAndQueueStatement.TestDirectExchange, QueueName = ExchangeAndQueueStatement.TestDirectQueue, RouteKey = ExchangeAndQueueStatement.TestDirectKey, }, body => { this .logger.LogInformation($ "收到消息{body}" ); return true ; }); }, TaskCreationOptions.LongRunning); return Task.CompletedTask; } public Task StopAsync(CancellationToken cancellationToken) { throw new NotImplementedException(); } } } |
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using RabbitCustorm; using RabbitCustorm.Message; namespace RabbitMqWebAPI.Controllers { [Route( "api/[controller]" )] [ApiController] public class RabbitProducerController : ControllerBase { private readonly ILogger<RabbitProducerController> logger; private readonly IProducer producer; private readonly static object lockobj = new object (); //一次访问资源的线程数量 1个 private static SemaphoreSlim _semaphore = new SemaphoreSlim(1); public RabbitProducerController(ILogger<RabbitProducerController> logger, IProducer producer) { this .logger = logger; this .producer = producer; } /// <summary> /// 发送直连消息 /// </summary> /// <param name="body"></param> /// <returns></returns> [HttpPost] public async Task<ActionResult> SendMessage([FromBody] string body) { await producer.SendMessageAsync( new MessageTrans { Definition = new ExchangeAndQueueDefinition { ExchangeName = ExchangeAndQueueStatement.TestDirectExchange, QueueName = ExchangeAndQueueStatement.TestDirectQueue, RouteKey = ExchangeAndQueueStatement.TestDirectKey }, Body = body }); return Ok( "发送成功!" ); } /// <summary> /// 发送延迟消息 /// </summary> /// <param name="body"></param> /// <returns></returns> [HttpPost( "SendDelayMessage" )] public async Task<ActionResult> SendDelayMessage([FromBody] Student body) { if (await _semaphore.WaitAsync(1000)) { await producer.SendMessageAsync( new MessageTrans { Definition = new ExchangeAndQueueDefinition { ExchangeName = ExchangeAndQueueStatement.TestExchange, QueueName = ExchangeAndQueueStatement.TestQueue, RouteKey = ExchangeAndQueueStatement.TestKey, Arguments = new Dictionary< string , object > { [ "x-message-ttl" ] = 12000, [ "x-dead-letter-exchange" ] = ExchangeAndQueueStatement.ExchangeDeadLetter, [ "x-dead-letter-queue" ] = ExchangeAndQueueStatement.QueueDeadLetter, [ "x-dead-letter-routing-key" ] = ExchangeAndQueueStatement.RouteDeadLetter, } }, Body = body }); } _semaphore.Release(); return Ok( "发送成功!" ); } } } |
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using RabbitCustorm; using RabbitCustorm.Message; namespace RabbitMqWebAPI.Controllers { [Route( "api/[controller]" )] [ApiController] public class RabbitConsumerController : ControllerBase { private readonly ILogger<RabbitConsumerController> logger; private readonly IConsumer consumer; public RabbitConsumerController(ILogger<RabbitConsumerController> logger, IConsumer consumer) { this .logger = logger; this .consumer = consumer; } [HttpGet] public ActionResult Received() { this .consumer.Received( new ExchangeAndQueueDefinition { ExchangeName = ExchangeAndQueueStatement.TestDirectExchange, QueueName = ExchangeAndQueueStatement.TestDirectQueue, RouteKey = ExchangeAndQueueStatement.TestDirectKey, }, body => { this .logger.LogInformation($ "收到消息{body}" ); return true ; }); return Ok(); } /// <summary> /// 接收死信队列消息 /// </summary> /// <returns></returns> [HttpGet( "ReceivedDeadLetter" )] public ActionResult ReceivedDeadLetter() { this .consumer.Received( new ExchangeAndQueueDefinition { ExchangeName = ExchangeAndQueueStatement.ExchangeDeadLetter, QueueName = ExchangeAndQueueStatement.QueueDeadLetter, RouteKey = ExchangeAndQueueStatement.RouteDeadLetter }, body => { this .logger.LogInformation($ "收到死信消息{body}" ); return true ; }); return Ok(); } } } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构