Masstransit框架中实现消息的动态监听

在使用消息队列中,会有这么一个场景:要求发送的queue是按照元数据配置自动生成,监听队列的逻辑也要对应的自动生成。这种

动态监听队列的场景可以使用Masstransit框架解决。

1.Producer

消息的生成者搭建一个webapi项目,指定virtual host,可以自动配置queue的名称

public void ConfigureServices(IServiceCollection services)
        {
            services.AddMassTransit(x => {
                x.UsingRabbitMq((context, config) =>
                {
                    config.Host("rabbitmq://localhost:5672", host =>
                    {
                        host.Username("root");
                        host.Password("root");
                    });
                });
            });
            services.AddControllers();
        }

然后写一个api程序

[ApiController]
    [Route("[controller]")]
    public class PublishController : ControllerBase
    {
        private readonly IPublishEndpoint _publishEndpoint;
        public PublishController(IPublishEndpoint  publishEndpoint)
        {
            _publishEndpoint = publishEndpoint;
        }
        
        [HttpGet]
        public async Task<string> Get(string name)
        {
            await _publishEndpoint.Publish(new OrderEto
            {
                Id = Guid.NewGuid(),
                Name = name,
                CreationTime = DateTime.Now
            });
            return "success";
        }
    }

 注意:OrderEto这个实体是共享同一个命名空间与名称的类

2.Consumer

消费者则使用通用主机项目

 public static async Task Main(string[] args)
        {
            await Host.CreateDefaultBuilder(args)
           .ConfigureServices(services =>
           {
               services.AddMassTransit(x =>
               {
                   x.AddConsumer<OrderEtoConsumer>(typeof(OrderEtoConsumerDefinition));
                   x.UsingRabbitMq((context, config) =>
                   {
                       config.Host("rabbitmq://localhost:5672", hostconfig =>
                       {
                           hostconfig.Username("root");
                           hostconfig.Password("root");
                       });

                       config.ConfigureEndpoints(context);

                   });
               });
           })
           .Build()
           .RunAsync();
        }

然后写一个consumer的类,这个类就是去消费的具体逻辑

public class OrderEtoConsumer : IConsumer<OrderEto>
    {

        public Task Consume(ConsumeContext<OrderEto> context)
        {
            Console.WriteLine($"MassTransit.Consumer.One 收到消息:{JsonSerializer.Serialize(context.Message)}");
            return Task.CompletedTask;
        }
    }

    public class OrderEtoConsumerDefinition : ConsumerDefinition<OrderEtoConsumer>
    {
        protected override void ConfigureConsumer(IReceiveEndpointConfigurator endpointConfigurator, IConsumerConfigurator<OrderEtoConsumer> consumerConfigurator)
        {
            endpointConfigurator.UseMessageRetry(r => r.Intervals(500, 1000));
        }
    }

将两个站点同时启动,进行测试:

 

 所以结论:

消费者的Model确定后,就相当于某类消息固定了,在不特指queue的情况下,可以监听所有queue的信息,如果在代码指定了具体的queue的名称则实现不了。

因为此时需要定义消息体跟consumer处理类。

posted @ 2022-10-21 15:22  DarryRing  阅读(91)  评论(0编辑  收藏  举报