Masstransit Azure Service Bus和DI请求/响应模型

时间:2018-05-31 13:42:23

标签: azureservicebus masstransit

我遇到了Azure Service Bus的问题,并与Masstransit和ASP.NET Core DI集成。 当我尝试为 IBus IRequestClient 设置DI并向请求端点发送消息时,我获得RequestTimeoutException但请求端点获取消息并对其进行处理。 当我尝试使用RabbitMQ做同样的事情或使用Azure Service Bus在本地创建IBus时,一切正常。 问题仅在我尝试通过ASP.NET Core DI设置Azure Service Bus时适用。

设置azure服务总线:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();

        var bus = InitBus();

        services.AddSingleton<IPublishEndpoint>(bus);
        services.AddSingleton<ISendEndpointProvider>(bus);
        services.AddSingleton<IBus>(bus);

        var timeout = TimeSpan.FromSeconds(10);
        var serviceAddress = new Uri("url");

        services.AddScoped<IRequestClient<SubmitOrder, OrderAccepted>>(x =>
            new MessageRequestClient<SubmitOrder, OrderAccepted>(x.GetRequiredService<IBus>(), serviceAddress, timeout, timeout));

        bus.Start();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment()) app.UseDeveloperExceptionPage();
        var bus = InitBus();

        bus.Start();

        app.UseMvc();
        //            app.Run();
    }

    public IBusControl InitBus()
    {
        var bus = Bus.Factory.CreateUsingAzureServiceBus(x => x.Host(new Uri(""), h =>
        {
            h.OperationTimeout = TimeSpan.FromSeconds(5);
            h.TokenProvider = TokenProvider.CreateSharedAccessSignatureTokenProvider("KeyName", "KeyValue");
        }));

        return bus;
    }
}

调用IRequestClient

[Route("api/[controller]")]
public class ValuesController : Controller
{
    private readonly IRequestClient<SubmitOrder, OrderAccepted> _requestClient;

    public ValuesController(IRequestClient<SubmitOrder, OrderAccepted> requestClient)
    {
        _requestClient = requestClient;
    }

    [HttpGet("{id}")]
    public async Task<IActionResult> Get(int id)
    {
        try
        {
            OrderAccepted result = await _requestClient.Request(new { OrderId = id });

            return Accepted(result.OrderId);
        }
        catch (RequestTimeoutException exception)
        {
            return StatusCode((int)HttpStatusCode.RequestTimeout);
        }
    }
}

接收器设置:

 class Program
{
    static void Main(string[] args)
    {
        Start().Wait();
    }

    public static async Task Start()
    {
        var bus = Bus.Factory.CreateUsingAzureServiceBus(cfg =>
        {
            var host = cfg.Host(new Uri("url"), h =>
            {
                h.OperationTimeout = TimeSpan.FromSeconds(5);
                h.TokenProvider = TokenProvider.CreateSharedAccessSignatureTokenProvider("KeyName", "KeyValue=");
            });

            cfg.ReceiveEndpoint(host, "order-service", e =>
            {
                e.Handler<SubmitOrder>(context => context.RespondAsync<OrderAccepted>(new
                {
                    context.Message.OrderId
                }));
            });
        });

        await bus.StartAsync();

        try
        {
            Console.WriteLine("Working....");

            Console.ReadLine();
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
        }
        finally
        {
            await bus.StopAsync();
        }
    }
}

1 个答案:

答案 0 :(得分:0)

首先,我建议查看创建的示例(使用RabbitMQ,但应该很容易转换为Azure Service Bus):

https://github.com/phatboyg/Sample-DotNetCore-DI

使用此示例正确完成DI使用模式。关于你的例子,有一些事情是不对的。您还使用了未正确捕获ConsumeContext响应跟踪的旧版请求客户端。