【问题标题】:ResolutionFailedException occurs randomly with no configuration changeResolutionFailedException 随机发生,无需更改配置
【发布时间】:2016-02-18 05:31:47
【问题描述】:

我有一个使用 Unity 块的 WCF 服务。

使用服务定位器模式解决依赖关系。

此服务每秒会收到多个请求,主要是在工作时间。托管它的应用程序池不托管其他进程,并在每天凌晨 2 点回收。

自安装以来,我们已经看到此错误发生了 3 次(1 月初、2 月初、今天),因此它非常断断续续。

我们得到的异常是:

Exception occurred while: while resolving.
Exception is: InvalidOperationException - The current type, ServiceContracts.IAuthService, is an interface and cannot be constructed. Are you missing a type mapping?

这可以通过在 Unity 容器上调用 .Resolve<T> 来解决。容器是静态的,在第一次被调用时配置

    _unityContainer = New Microsoft.Practices.Unity.UnityContainer()
    _unityContainer.AddNewExtension(Of Microsoft.Practices.Unity.InterceptionExtension.Interception)()
    _unityContainer.AddNewExtension(Of Microsoft.Practices.EnterpriseLibrary.Common.Configuration.Unity.EnterpriseLibraryCoreExtension)()

    _unityContainer.LoadConfiguration()

我认为配置没有任何问题,因为这只发生在一个安装站点(服务安装在其他位置没有问题)。

Unity 版本为2.0.414.0

Unity配置通过web.config进行,如:

<unity>
    <container>
        <register type="ServiceContracts.IAuthService, ServiceContracts" mapTo="ServiceContracts.AuthService, ServiceImp" />
    </container>
</unity>

更新添加

每个服务实现都有两个 ctor - 一个没有参数,另一个带有用于测试的参数注入。 WCF 调用的无参数 ctor 包含对辅助类 (Unity) 的调用,该类是 Unity 容器上的一个非常薄的包装器,并实现了服务定位器模式。

所以对于包装所描述的 IAuthService 的类,ctor 看起来像这样:

private IAuthService _authService;

public AuthWrapper()
{
    _authService = Unity.Resolve<IAuthService>();
}

VB.NET 中的 Unity 助手类如下所示:

Public NotInheritable Class Unity

    Private Shared _unityContainer As IUnityContainer

    Public Shared Function Resolve(Of T)() As T
        If _unityContainer Is Nothing Then Call configure()
        Return _unityContainer.Resolve(Of T)()
    End Function

    Private Shared Sub configure()
        _unityContainer = New Microsoft.Practices.Unity.UnityContainer()   
        _unityContainer.LoadConfiguration()
    End Sub

End Class

【问题讨论】:

  • 您能否显示更多关于何时调用LoadConfiguration 的信息(和代码)?例如它驻留在什么文件和方法上?
  • @RandyLevy 我会把它添加到原始问题中,给我 5 分钟的时间输入。
  • 感谢您更新代码。你的代码绝对不是线程安全的,所以我要做的第一件事就是修复它。看起来你想要一个单例(使用共享函数),但你并没有阻止多个线程访问共享的 _unityContainer。如果使用 .NET 4+,您可以使用 Lazy&lt;T&gt; 以线程安全的方式初始化容器。如果没有,那么您可以在以下位置调整其他单例方法之一:csharpindepth.com/Articles/General/Singleton.aspx
  • @RandyLevy 这怎么不是线程安全的?容器在启动时加载,从容器读取不需要锁定,因为它没有被修改?

标签: .net wcf unity-container enterprise-library


【解决方案1】:

InvalidOperationException -- 这表示接口没有在容器中注册。

为什么会发生这种情况?如果LoadConfiguration 仅在启动时调用一次,则似乎注册在容器中丢失(我以前从未见过)或容器已创建但LoadConfiguration 尚未调用。后者似乎更有可能。也许应用程序池已关闭/回收(超时?),然后两个请求同时进入。引导期间可能存在竞争条件(由于发布的代码不完整,因此无法确定)。

例如请求 #1 进来并创建了容器。同时请求 #2 进来,找到创建的容器并尝试解析。但是,请求 #2 的解析发生在请求 #1 完成加载容器配置之前。该场景解释了所描述的行为,但是,如果没有更多信息,尚不清楚这是否是这种情况下实际发生的情况。

【讨论】:

  • 嗨,@RandyLevy,我在帖子中添加了更多信息。您的解释可能是有道理的,但我们已经使这项服务承受了非常重的负载,并且在我们的测试中从未见过这种情况。此外,如果比赛请求是正确的,那么您会假设以下请求将填充容器。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-11-27
  • 1970-01-01
  • 2010-10-28
  • 2019-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多