• 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 对异常的消息可以进行重新投递

  • 相关阅读:
    Oracle序列更新
    ssh服务器终端乱码
    iTerm2常用的快捷键
    原来 Set 集合也可以排序
    Java 单例
    java后台技术
    网易考拉规则引擎平台架构设计与实践
    HBase最佳实践(好文推荐)
    如何通俗的解释云
    写的不错的一篇云数据库的文章
  • 原文地址:https://www.cnblogs.com/ansheng/p/16103902.html
Copyright © 2020-2023  润新知