簡體   English   中英

NServiceBus IUniformSession 不適用於 Azure WebJobs SDK

[英]NServiceBus IUniformSession does not work with Azure WebJobs SDK

我無法讓 IUniformSession 在帶有通用主機的 Azure WebJobs SDK 項目中工作。 我正在使用 .NET 內置 DI。 我在下面創建了一個緊湊的復制品。

我在用

  • NServiceBus 7.7.4
  • NServiceBus.Extensions.Hosting 1.1.0
  • NServiceBus.UniformSession 2.2.0
  • Microsoft.Azure.WebJobs 3.0.33
  • .NET 6

預期行為

當類(“作業”)被實例化時,IUniformSession 被解析為依賴項。

實際行為

IUniformSession 始終解析為 NULL。 一些快速斷言(如下所示)表明 IUniformSession 已在 DI 容器中注冊,因此 .EnableUniformSession() 正確執行此操作,但當請求實例時,它始終解析為 NULL。

重現步驟

csproj

<ItemGroup>
    <PackageReference Include="Microsoft.Azure.WebJobs" Version="3.0.33" />
    <PackageReference Include="Microsoft.Azure.WebJobs.Extensions" Version="4.0.1" />
    <PackageReference Include="Microsoft.Azure.WebJobs.Extensions.Storage" Version="5.0.1" />
    <PackageReference Include="Microsoft.Azure.WebJobs.Host.Storage" Version="4.1.0" />
    <PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.1" />
    <PackageReference Include="NServiceBus" Version="7.7.4" />
    <PackageReference Include="NServiceBus.Extensions.Hosting" Version="1.1.0" />
    <PackageReference Include="NServiceBus.UniformSession" Version="2.2.0" />
    <PackageReference Include="Serilog" Version="2.11.0" />
    <PackageReference Include="Serilog.Extensions.Hosting" Version="5.0.1" />
    <PackageReference Include="Serilog.Sinks.Console" Version="4.0.1" />
  </ItemGroup>

程序.cs

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using NServiceBus;
using NServiceBus.UniformSession;
using NSUniformSessionRepro.DemoClasses;
using Serilog;

// Setup the ability to read config files
var configurationBuilder = new ConfigurationBuilder()
     .SetBasePath(Directory.GetCurrentDirectory())
     // then read the environment variables (in Azure) which will override some settings from the local settings
     .AddEnvironmentVariables();
var configuration = configurationBuilder.Build();

var builder = new HostBuilder();
builder
    .UseSerilog(Log.Logger)
    .ConfigureAppConfiguration((context, config) =>
    {
        config.AddConfiguration(configuration);
    })
    .ConfigureWebJobs(b =>
    {
        b.AddAzureStorageCoreServices()
        .AddAzureStorageBlobs()
        .AddAzureStorageQueues()
        .AddTimers();
    });

IServiceCollection _serviceCollection = null;

builder.ConfigureServices(services =>
{
    services.AddTransient<IMessagingService, MessagingService>();
    _serviceCollection = services;
    
});

builder.UseNServiceBus(context =>
{
    var endpointConfiguration = new EndpointConfiguration("MyEndpoint");

    endpointConfiguration.EnableUniformSession();
    endpointConfiguration.UseTransport<LearningTransport>();
    endpointConfiguration.UsePersistence<LearningPersistence>();
    // configure endpoint here
    return endpointConfiguration;
});


var host = builder.Build();

var isUniformSessionRegistered = _serviceCollection.Any(x => x.ServiceType == typeof(IUniformSession));
Console.WriteLine("UniformSession is registered in DI: " + isUniformSessionRegistered);

using (host)
{
    await host.RunAsync();
}



static void ConfigureLogging(IConfigurationRoot configuration)
{
    var loggerConfiguration = new LoggerConfiguration()
        .MinimumLevel.Information()
        .WriteTo.Console();

    Log.Logger = loggerConfiguration
        .CreateLogger();
}

MessagingService.cs(只是一個虛擬的 class,它本身依賴於 IUniformSession)

public interface IMessagingService
    {
        // public for testing
        IUniformSession UniformSession { get; set; }
        Task Send(object message);
    }

    public class MessagingService : IMessagingService
    {
        // public for testing
        public IUniformSession UniformSession { get; set; }

        public MessagingService(IUniformSession uniformSession)
        {
            UniformSession = uniformSession;
        }

        public async Task Send(object message)
            => await UniformSession.Send(message);
    }

演示工作

public class DemoJob
    {
        private readonly IMessagingService _messagingService;

        public DemoJob(IMessagingService messagingService)
        {
            _messagingService = messagingService;
        }

        public void DummyJob([TimerTrigger("0 0 12 * * *", RunOnStartup = true, UseMonitor = false)] TimerInfo timer, TextWriter log)
        {
            // no-op
            // for testing puporses
            if (_messagingService.UniformSession == null)
                Console.Write("UniformSession was NULL");
        }
    }

任何幫助將不勝感激。

這有點棘手,因為主機的設置方式會由於啟動順序而導致一些問題。

首先,我不確定您為什么要通過IMessagingServiceIUniformSession上構建自己的抽象,所以我將把它省略掉。 請記住, IUniformSession已經是IMessageSession (這就是你在這里所需要的)和IMessageHandlerContext的抽象。

您應該能夠通過在調用builder.UseNServiceBus之前將調用移動到builder.ConfigureWebJobs來依賴IUniformSessionIMessageSession ,例如:

builder
    .UseSerilog(Log.Logger)
    .ConfigureAppConfiguration((context, config) =>
    {
        config.AddConfiguration(configuration);
    })
    .UseNServiceBus(context =>
    {
        var endpointConfiguration = new EndpointConfiguration("MyEndpoint");

        endpointConfiguration.EnableUniformSession();
        endpointConfiguration.UseTransport<LearningTransport>();
        endpointConfiguration.UsePersistence<LearningPersistence>();
        // configure endpoint here
        return endpointConfiguration;
    })
    .ConfigureWebJobs(b =>
    {
        b.AddAzureStorageCoreServices()
        .AddAzureStorageBlobs()
        .AddAzureStorageQueues()
        .AddTimers();
    });

這將確保在 web 作業相關代碼之前配置和啟動 NServiceBus,以便可以在正確的時間點通過 DI 注入所需的服務。

請注意,使用IMessageSession應該在前面指出這一點,因為 NServiceBus 通用主機支持具有顯式代碼來檢測統一 session 沒有的此類排序問題

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM