大众运输-如何使用Azure Service Bus安排消息

时间:2019-08-07 04:57:02

标签: c# azure azureservicebus masstransit

我已经查看了有关Scheduling with Azure Service Bus的文档,但不清楚如何从“断开连接的”总线发送消息。

这是我配置用于处理服务器上消息的服务的方式:

builder.AddMassTransit(mt =>
{
    mt.AddConsumers(cqrsAssembly);

    mt.AddBus(context => Bus.Factory.CreateUsingAzureServiceBus(x =>
    {
        x.RequiresSession = true;
        x.MaxConcurrentCalls = 500;
        x.MessageWaitTimeout = TimeSpan.FromMinutes(5);
        x.UseRenewLock(TimeSpan.FromMinutes(4));
        x.UseServiceBusMessageScheduler();

        var host = x.Host(serviceUri, h =>
        {
            h.SharedAccessSignature(s =>
            {
                s.KeyName = "key-name";
                s.SharedAccessKey = "access-key";
                s.TokenTimeToLive = TimeSpan.FromDays(1);
                s.TokenScope = TokenScope.Namespace;
            });

            h.OperationTimeout = TimeSpan.FromMinutes(2);
        });

        x.ReceiveEndpoint(host, $"mt.myqueue", ep =>
        {
            ep.RequiresSession = true;
            ep.MaxConcurrentCalls = 500;
            ep.RemoveSubscriptions = true;

            ep.UseMessageRetry(r =>
            {
                r.Interval(4, TimeSpan.FromSeconds(30));
                r.Handle<TransientCommandException>();
            });

            ep.ConfigureConsumers(context);
        });
    });
});

我已明确致电UseServiceBusMessageScheduler()

在创建消息并将消息发送到队列的项目中(在不同的上下文中运行,因此只发送了消息),我们具有以下条件:

var bus = Bus.Factory.CreateUsingAzureServiceBus(x =>
{
    x.RequiresSession = true;
    x.MessageWaitTimeout = TimeSpan.FromMinutes(5);
    x.UseRenewLock(TimeSpan.FromMinutes(4));
    x.Send<ICommand>(s => s.UseSessionIdFormatter(ctx => ctx.Message.SessionId ?? Guid.NewGuid().ToString()));


    var host = x.Host(serviceUri, h =>
    {
        h.SharedAccessSignature(s =>
        {
            s.KeyName = "key-name";
            s.SharedAccessKey = "key"; 
            s.TokenTimeToLive = TimeSpan.FromDays(1);
            s.TokenScope = TokenScope.Namespace;
        });
        h.OperationTimeout = TimeSpan.FromMinutes(2);
    });

    EndpointConvention.Map<ICommand>(new Uri($"{serviceUri.ToString()}mt.myqueue"));
    EndpointConvention.Map<Command>(new Uri($"{serviceUri.ToString()}mt.myqueue"));
});

现在,要发送预定的消息,我们可以这样做:

var dest = "what?";
await bus.ScheduleSend(dest, scheduledEnqueueTimeUtc.Value, message);

我不确定需要将什么传递到destinationAddress

我尝试过: -serviceUri -`{serviceUri} mt.myqueue“

但是检查队列时,我在基本队列,skipped队列或error队列中都看不到消息。

我是否缺少其他配置,如果没有,那么如何确定目标队列?

我使用的是大众运输版本5.5.4ScheduleSend()的每次重载都需要它。

1 个答案:

答案 0 :(得分:2)

首先,是的,您的Uri格式正确。最后,在格式化之后,您需要这样的东西:

new Uri(@"sb://yourdomain.servicebus.windows.net/yourapp/your_message_queue")

还要确保在配置endPoint时已添加。 (请参阅下面的链接)

configurator.UseServiceBusMessageScheduler();

如果您遵循大众运输文档,则从ConsumeContext进行调度。参见Mass-Transit Azure Scheduling

public class ScheduleNotificationConsumer :
    IConsumer<AssignSeat>
{
    Uri _schedulerAddress;
    Uri _notificationService;

    public async Task Consume(ConsumeContext<AssignSeat> context)
    {
        if(context.Message.ReservationTime - DateTime.Now < TimeSpan.FromHours(8))
        {
            // assign the seat for the reservation
        }
        else
        {
            // seats can only be assigned eight hours before the reservation
            context.ScheduleMessage(context.Message.ReservationTime - TimeSpan.FromHours(8), context.Message);
        }
    }
}

但是,在我们本周面对的一个用例中,我们需要从外部消费上下文进行调度,或者根本不想将上下文转发到我们计划的位置。使用IBusControl.ScheduleSend时,我们不会收到错误反馈,但实际上也没有完成任何调度。  在查看了Mass-Transit所做的事情之后,它从IBusControl中发现,它创建了一个新的调度提供程序。而从上下文中,它使用ServiceBusScheduleMessageProvider。

因此,在清除此位之前,我们现在要做的是直接调用ServiceBusScheduleMessageProvider。

        await new ServiceBusScheduleMessageProvider(_busControl).ScheduleSend(destinationUri
            , scheduleDateTime.UtcDateTime
            , Task.FromResult<T>(message)
            , Pipe.Empty<SendContext>()
            , default);

希望这有意义并有所帮助。