繁体   English   中英

MassTransit 状态机配置

[英]MassTransit State Machine Configuration

在使用状态机 saga 时,如何将 MassTransit 配置为使用仲裁队列而不是经典队列? 在下面的代码中,如果我取消注释 cfg.ReceiveEndpoint(x => x.SetQuorumQueue()) 行,它仍然会创建经典队列。

另外,我在哪里使用 UseScheduledRedelivery 和 UseMessageRetry 方法来配置重试和重新发送?

    public static IServiceCollection RegisterMassTransit(
        this IServiceCollection services,
        string sagaStateConnectionString,
        SerilogLoggerFactory factory,
        TransportSettings transportSettings)
    {
        services.AddDbContext<OrderSagaDbContext>(r =>
        {
            r.UseSqlServer(sagaStateConnectionString, m =>
            {
                m.MigrationsAssembly(Assembly.GetExecutingAssembly().GetName().Name);
                m.MigrationsHistoryTable($"__{nameof(OrderSagaDbContext)}");
            });
        });


        services.AddMassTransit(c =>
        {
            c.SetKebabCaseEndpointNameFormatter();

            c.AddSagaStateMachine<OrderStateMachine, OrderState>()
                .EntityFrameworkRepository(r =>
                {
                    r.ExistingDbContext<OrderSagaDbContext>();
                    r.UseSqlServer();
                });

            c.AddBus(context => ConfigureBus(context, transportSettings));

            foreach (var q in transportSettings.Queues)
            {
                c.AddConsumers(TypeNamesToTypes(q.Processors));
                
            }
        });

        return services;
    }

    private static IBusControl ConfigureBus(
        IBusRegistrationContext context,
        TransportSettings transportSettings)
    {
        return Bus.Factory.CreateUsingRabbitMq(cfg =>
        {
            cfg.Host(transportSettings.Host, transportSettings.VirtualHost, hst =>
            {
                hst.Username(transportSettings.UserName);
                hst.Password(transportSettings.Password);
            });
            
            //cfg.ReceiveEndpoint(x => x.SetQuorumQueue());
            cfg.ConfigureEndpoints(context);

        });
    }

要覆盖 saga 端点的接收端点配置,您可以创建一个 saga 定义:

public class OrderStateSagaDefinition :
    SagaDefinition<OrderState>
{
    protected override void ConfigureSaga(IReceiveEndpointConfigurator endpointConfigurator, ISagaConfigurator<OrderState> sagaConfigurator)
    {
        if(endpointConfigurator is IRabbitMqReceiveEndpointConfigurator rmq)
            rmq.SetQuorumQueue();

        endpointConfigurator.UseScheduledRedelivery(...);
        endpointConfigurator.UseMessageRetry(...);
        endpointConfigurator.UseInMemoryOutbox();
    }
}

您还可以在定义中配置消息重试/重新传递/发件箱,如图所示。

然后,将该定义添加到容器配置中:

c.AddSagaStateMachine<OrderStateMachine, OrderState, OrderStateSagaDefinition>()

您还需要配置调度程序。 如果您使用 RabbitMQ 延迟交换进行重新交付, UseScheduledRedelivery UseScheduledRedelivery 更改为UseDelayedRedelivery

在上面 Chris 的帮助下,我能够弄清楚如何为使用多个队列和状态机传奇的应用程序中的所有队列设置属性。

添加扩展方法如下:

public static class RabbitMqReceiveEndpointConfigurationExtensions
{
    public static void Configure(
        this RabbitMqReceiveEndpointConfiguration rmq)
    {
        rmq.PublishFaults = ...;
        rmq.PrefetchCount = ...;
        rmq.SetQuorumQueue();
        rmq.UseScheduledRedelivery(...);
        rmq.UseMessageRetry(...);
    }
}

然后我们可以在配置容器时为每个队列调用扩展方法,如下:

services.AddMassTransit(c =>
{
    c.SetKebabCaseEndpointNameFormatter();
    c.AddConfigureEndpointsCallback((endpoint, endpointConfigurator) =>
    {
        if (endpointConfigurator is RabbitMqReceiveEndpointConfiguration rmq)
        {
            rmq.Configure();
        }
    });
    ...
});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM