簡體   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