【问题标题】:WCF + Spring.NET causing intermittent System.Transaction exceptionsWCF + Spring.NET 导致间歇性 System.Transaction 异常
【发布时间】:2012-01-27 02:36:33
【问题描述】:

一段时间以来,我一直在 Web 应用程序中使用 Spring.NET 的声明式事务,没有出现任何问题。事务建议仅应用于服务层方法。

我们最近部署了两个 WCF 服务,它们使用我们的 Spring 托管服务对象作为依赖项。我们使用Spring.ServiceModel.Activation.ServiceHostFactory 根据 Spring.NET 示例实例化这些服务。

在将这些服务部署到生产后不久,我们就遇到了来自管理 Spring 事务的 AdoPlatformTransactionManager 类的间歇性错误。

错误文本是:

    System.ObjectDisposedException: Cannot access a disposed object.
    Object name: 'Transaction'.
       at System.Transactions.Transaction.get_IsolationLevel()
       at System.Transactions.TransactionScope..ctor(TransactionScopeOption scopeOption, TransactionOptions 
at AdoPlatformTransactionManager.DoBegin(Object transaction, ITransactionDefinition definition)
at Spring.Transaction.Support.AbstractPlatformTransactionManager.GetTransaction(ITransactionDefinition definition) 

这些错误是间歇性的,并且似乎与当前服务器负载相关(更多用户 = 重现的可能性更高)。此外,我们在任何非 WCF 启动的服务方法调用中都没有看到此类异常。到目前为止,我有两个非常不稳定的理论要继续:

  • WCF 对象实例化/范围 (PerCall) 不能很好地与单例服务对象配合使用
  • 某种并发问题,其中多个 WCF 服务实例能够干扰其他不相关实例的环境事务(线程本地存储?)

谷歌搜索此错误并搜索大部分无人问津的 Spring.NET 支持论坛一无所获,因此感谢任何帮助或想法!

更新 1

进行了更多调试,并更清楚地解决了这个问题。看来真正的问题与事务无关,而是与从故障状态恢复 WCF 通道有关。

任何时候在 WCF 方法调用期间抛出未处理的异常(在我的情况下是违反 FK),通道似乎处于永久故障状态。

更糟糕的是,一旦通道进入故障状态,它会影响该服务的所有用户,因为 Spring.NET 不会为每个用户创建新通道。解决此问题的唯一方法似乎是回收应用程序池。

根据下面引用的链接,我不确定问题是出在 Spring.NET、WCF 故障还是其他原因。

参考文献

client-timeout-when-using-wcf-through-spring-net

Best-Practices-and-Recover-a-Faulted-Channel

what-is-the-best-workaround-for-the-wcf-client-using-block-issue

【问题讨论】:

    标签: asp.net multithreading wcf transactions spring.net


    【解决方案1】:

    您是否将 ServiceHostFactory 导出的服务声明为“原型”对象,即不是单例,以便与 WCF 实例正确交互?

    <object id="calculator" singleton="false" type="Spring.WcfQuickStart.CalculatorService, Spring.WcfQuickStart.ServerApp">
      <property name="SleepInSeconds" value="1"/>
    </object>
    

    【讨论】:

    • 嗨,bbaia,导出的服务本身就是一个原型。但是,服务的依赖项(主要是 Dao 的)是单例而不是原型。服务及其整个依赖图是否需要成为原型?如果是这样,我怎样才能做到这一点而不破坏我的应用程序的其他部分,这些部分依赖于我的 DAO 的单例行为?
    • 消费的服务只有在线程安全的情况下才能是单例的。他们是吗? Spring.net 不支持开箱即用的 instance-per-graph 范围。我通常用原型范围声明我的 dao。您的应用依赖于单例行为的哪个方面?
    • 我的单例绝对是线程安全的(完全无状态)。我假设 Spring.NET 的事务管理也是线程安全的?
    • Spring.NET 管理每个线程、每个 dbprovider 的事务。但是 NHibernate 的会话(例如)不是线程安全的,因此很难判断您的实现是否真的是线程安全的:您的单例显然是无状态的,但它们是否以线程安全的方式消耗非线程安全的依赖项?无论如何,从您问题的更新来看,我认为线程问题不是这里的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多