• MassTransit .NET Core 分布式事务


    使用 .NET 5 + MassTransit 8.0.1 实现一个分布式事务,并保证最终一致性

    WebAPI

    readonly ISendEndpointProvider _sendEndpointProvider;
    public DemoController(ISendEndpointProvider sendEndpointProvider)
    {
        _sendEndpointProvider = sendEndpointProvider;
    }
    
    [HttpGet]
    public async Task<ActionResult> Get(string id)
    {
        string message = "Meeeeeeeee" + id;
        var endpoint = await _sendEndpointProvider.GetSendEndpoint(new Uri("queue:DeductStock_Queue"));
        await endpoint.Send<DeductStockDto>(new
        {
            Id = id,
            Message = message
        });
        return Ok();
    }

    Startup

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews();
        services.AddMassTransit(x =>
        {
            x.UsingRabbitMq((context, cfg) =>
            {
                cfg.Host(new Uri("rabbitmq://192.168.214.129/MassTransit_vhost"), c =>
                {
                    c.Username("guest");
                    c.Password("guest");
                });
            });
        });
        services.Configure<MassTransitHostOptions>(options =>
        {
            options.WaitUntilStarted = true;
            options.StartTimeout = TimeSpan.FromSeconds(30);
            options.StopTimeout = TimeSpan.FromMinutes(1);
        });
    }

    减库存·

    static void Main(string[] args)
    {
        Console.Title = "减库存";
    
        var builder = new HostBuilder();
        builder.ConfigureServices((hostContext, services) =>
        {
            services.AddMassTransit(x =>
            {
                x.AddConsumer<DeductStockConsumer>();
                x.AddConsumer<DeductStockErrorConsumer>();
                x.UsingRabbitMq((context, cfg) =>
                {
                    cfg.Host(new Uri("rabbitmq://192.168.214.129/MassTransit_vhost"), c =>
                    {
                        c.Username("guest");
                        c.Password("guest");
                    });
    
                    cfg.ReceiveEndpoint("DeductStock_Queue", e =>
                    {
                        e.ConfigureConsumer<DeductStockConsumer>(context);
                    });
    
                    cfg.ReceiveEndpoint("DeductStock_Queue_error", e =>
                    {
                        e.ConfigureConsumer<DeductStockErrorConsumer>(context);
                    });
                });
            });
    
            services.Configure<MassTransitHostOptions>(options =>
            {
                options.WaitUntilStarted = true;
                options.StartTimeout = TimeSpan.FromSeconds(30);
                options.StopTimeout = TimeSpan.FromMinutes(1);
            });
        })
        .Build().Run();
    }

    DeductStockConsumer

    public class DeductStockConsumer : IConsumer<DeductStockDto>
    {
        public async Task Consume(ConsumeContext<DeductStockDto> context)
        {
            Console.WriteLine("扣库存:" + context.Message.Id);
    
            if (context.Message.Id % 10 == 1 && !context.Message.IsBug)
            {
                throw new Exception("");
            }
    
    
    
            var endpoint = await context.GetSendEndpoint(new Uri("queue:DeductBalance_Queue"));
            await endpoint.Send<DeductBalanceDto>(new
            {
                Id = context.Message.Id,
                Message = context.Message.Message + ":DeductStockConsumer",
                IsBug = context.Message.IsBug,
                RetryCount = context.Message.RetryCount
            });
    
            //return Task.CompletedTask;
        }
    }
    
    public class DeductStockDto
    {
        public int Id { get; set; }
        public int DeductStock { get; set; }
        public int DeductBalance { get; set; }
        public string Message { get; set; }
        public bool IsBug { get; set; }
        public int RetryCount { get; set; }
    }

    DeductStockErrorConsumer

    public class DeductStockErrorConsumer : IConsumer<DeductStockDto>
    {
        public async Task Consume(ConsumeContext<DeductStockDto> context)
        {
            Console.WriteLine("减库存异常:" + context.Message.Id);
            if (context.Message.RetryCount >= 5)
            {
                throw new Exception();
            }
            context.Message.RetryCount += 1;
            context.Message.IsBug = true;
            var endpoint = await context.GetSendEndpoint(new Uri("queue:DeductStock_Queue"));
            await endpoint.Send<DeductStockDto>(new
            {
                Id = context.Message.Id,
                Message = context.Message.Message + ":DeductStockConsumer",
                IsBug = context.Message.IsBug,
                RetryCount = context.Message.RetryCount
            });
        }
    }

    异常重试

    e.UseMessageRetry(r =>
    {
        r.Immediate(20);
    });

    如果出现异常,MassTransit 会自动创建一个错误队列

    如果消息未被消费,MassTransit 会自动创建一个死信队列

    MassTransit 对异常的消息可以进行重新投递

  • 相关阅读:
    图解隐马尔科夫模型【会其意】
    基于mysql对mybatis中的foreach进行深入研究
    JS-安全检测JavaScript基本数据类型和内置对象的方法
    Java-生成指定长度验证码的一种简单思路
    jQuery-表单流程导航
    JS-获取URL请求参数
    AngularJS-Uncaught Error: [$injector:modulerr]
    AngularJS-系统代码的配置和翻译
    JS-改变页面的颜色之变化核心-获取六位的随机数
    JS-为金额添加千分位逗号分割符
  • 原文地址:https://www.cnblogs.com/ansheng/p/16103902.html
Copyright © 2020-2023  润新知