带有简单喷油器的 Rebus 中断性更改



场景:

  • 使用多个卫星库的 Web API 应用程序
  • .NET Framework 4.6
  • 简单喷油器
  • 画谜
  • Rebus.AzureServiceBus
  • Rebus.SimpleInjector

在我的应用程序中,有多个卫星库,其中大多数都有一个实现 SimpleInjectorIPackage接口的类,即对不同库中的容器注册进行分组。这些包在启动时注册

container.RegisterPackages(AppDomain.CurrentDomain.GetAssemblies());

其中一个包包含 Rebus 配置

IContainerAdapter adapter = new SimpleInjectorContainerAdapter( container );
Configure.With( adapter )
.Transport( t => t.UseAzureServiceBusAsOneWayClient( connectionString, AzureServiceBusMode.Standard ) )
.Routing( r =>
r.TypeBased()
.MapAssemblyOf<TransactionCreated>( "MyQueue" )
)
.Options( oc => {
oc.SetNumberOfWorkers( 1 );
} )
.Start();

今天早上,我们将 Rebus 软件包升级到以下版本:

  • Rebus 4.0.1
  • Rebus.AzureServiceBus 4.0.0
  • Rebus.SimpleInjector 4.0.0

升级后系统停止工作,现在我们收到以下错误

容器在第一次调用 GetInstance 后无法更改, GetAllInstances 并验证。请看 https://simpleinjector.org/locked 了解容器为什么 锁。以下堆栈跟踪描述了 容器已锁定:

通过对代码进行调试,我们可以看到在注册 rebus 的包之后注册了另一个包,因此错误的原因。我们可以确认代码没有进行任何修改,并且在以前的版本中按预期正确工作。

我还可以确认,通过降级到这些版本,问题消失了

  • Rebus 3.1.5
  • Rebus.AzureServiceBus 3.0.0
  • Rebus.SimpleInjector 3.0.0

有什么建议吗?

编辑:根据@Steven要求,我正在添加完整的堆栈跟踪

说明:执行 当前 Web 请求。请查看堆栈跟踪以获取更多信息 有关错误及其在代码中起源位置的信息。

异常详细信息:系统无效操作异常:容器 第一次调用 GetInstance、GetAllInstances 后无法更改 并验证。请参阅 https://simpleinjector.org/locked 以了解 为什么容器被锁定。以下堆栈跟踪描述了 容器的锁定位置:

at Rebus.SimpleInjector.SimpleInjectorContainerAdapter.SetBus(IBus bus)   
at Rebus.Config.RebusConfigurer.Start()
at XXX.YYY.EndpointEvents.Producer.IOC.EndpointEventsProducerModule.RegisterServices(Container container) 
at SimpleInjector.PackageExtensions.RegisterPackages(Container container, IEnumerable assemblies)
at XXX.YYY.WebAPI.SimpleInjectorWebApiInitializer.InitializeContainer(Container container) 
at XXX.YYY.WebAPI.SimpleInjectorWebApiInitializer.Initialize() 
at XXX.YYY.WebAPI.Startup.Configuration(IAppBuilder app)
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at Owin.Loader.DefaultLoader.<>c__DisplayClass12.<MakeDelegate>b__b(IAppBuilder builder)
at Owin.Loader.DefaultLoader.<>c__DisplayClass1<LoadImplementation>b__0(IAppBuilder builder) 
at Microsoft.Owin.Host.SystemWeb.OwinHttpModule.<>c__DisplayClass2.<InitializeBlueprint>b__0(IAppBuilder builder) 
at Microsoft.Owin.Host.SystemWeb.OwinAppContext.Initialize(Action startup)
at Microsoft.Owin.Host.SystemWeb.OwinBuilder.Build(Action startup)
at Microsoft.Owin.Host.SystemWeb.OwinHttpModule.InitializeBlueprint()  
at System.Threading.LazyInitializer.EnsureInitializedCore[T](T& target, Boolean& initialized, Object& syncLock, Func valueFactory)  
at Microsoft.Owin.Host.SystemWeb.OwinHttpModule.Init(HttpApplication context)  
at System.Web.HttpApplication.RegisterEventSubscriptionsWithIIS(IntPtr appContext, HttpContext context, MethodInfo[] handlers)
at System.Web.HttpApplication.InitSpecial(HttpApplicationState state, MethodInfo[] handlers, IntPtr appContext, HttpContext context)
at System.Web.HttpApplicationFactory.GetSpecialApplicationInstance(IntPtr appContext, HttpContext context)
at System.Web.Hosting.PipelineRuntime.InitializeApplication(IntPtr appContext)

很抱歉迟到了对这个问题的反应:)

我终于有时间了解 SimpleInjector 希望如何进行容器注册,并了解 Rebus 配置 API 如何以某种方式以这种方式工作。

事实证明,通常

Configure.With(new MyFavoriteContainerAdapter(container))
.(...)
.Start();

咒语必须以某种方式移动到Func<IBus>中,以便在实际启动总线之前完成所有与 Rebus 相关的注册(以及您自己的注册(。

结果(刚刚在 Rebus.SimpleInjector 5.0.0-b01 中发布 NuGet.org(是这个 API:

public class RebusPackage : IPackage
{
public void RegisterServices(Container container)
{
Console.WriteLine("Calling RebusPackage");
container.ConfigureRebus(
configurer => configurer
.Transport(t => t.UseInMemoryTransport(new InMemNetwork(), "test"))
.Start()
);
}
}

如果你使用SimpleInjector.Packaging,或者只是简单地说,这就是它的样子

container.ConfigureRebus(
configurer => configurer
.Transport(t => t.UseInMemoryTransport(new InMemNetwork(), "test"))
.Start()
);

如果您拥有的只是一个简单注射器container.

当您认为是时候启动公共汽车时,您要么

container.StartBus();

或者你等到IBus得到解决。

正如您在这里看到的,添加了新的编码以确保总线被处置,这引入了一个问题,您的代码似乎很好,只需要等待修复即可。新行下方

+            // cheat and activate the IBus singleton behind the scenes, thus ensuring that the container will dispose it when it is time
+            var registration = _container.GetRegistration(typeof(IBus));
+  +            registration.GetInstance();
+

您的EndpointEventsProducerModule正在调用RebusConfigurer.Start。"启动"解析容器中的IBus

由于可以按任意顺序调用模块,因此只应在模块中进行注册。删除Start调用,并在调用容器后调用它。验证((。

相关内容

  • 没有找到相关文章

最新更新