【问题标题】:Thread aborted exceptions in wcf servicewcf 服务中的线程中止异常
【发布时间】:2016-10-21 13:53:33
【问题描述】:

我有一个托管在 IIS 6.0 上的 WCF 服务(内置于 .NET 框架 3.5)。

代码流程如下

  1. 客户端(这是另一个 Web 服务)调用 WCF 服务
  2. WCF 服务调用线程在后台进行处理并立即响应被调用方。
  3. 后台线程完成所有处理后,回调线程。这个调用基本上是一个 HTTPs 请求,因为客户端是一个 Web 服务。

我正在对我的 WCF 服务进行负载测试以定义阈值。观察结果如下:

在 1 分钟内向 WCF 服务发出的 1024 个请求大约 3 次迭代成功通过。完成每次迭代所需的时间约为 25-30 分钟。 然而,从第 4 次迭代中可以看到批量失败。大约 50% 的请求失败,以下例外。

异常线程被中止。

堆栈跟踪

21_10_2016_09_30_52,9:30:52 AM,Information,Thread name- apSwTTbLTETfwT3y Stack trace in ProcessTestConversion method -    at System.Threading.WaitHandle.WaitOneNative(SafeHandle waitableSafeHandle, UInt32 millisecondsTimeout, Boolean hasThreadAffinity, Boolean exitContext)
   at System.Threading.WaitHandle.InternalWaitOne(SafeHandle waitableSafeHandle, Int64 millisecondsTimeout, Boolean hasThreadAffinity, Boolean exitContext)
   at System.Threading.WaitHandle.WaitOne(Int32 millisecondsTimeout, Boolean exitContext)
   at System.Net.LazyAsyncResult.WaitForCompletion(Boolean snap)
   at System.Net.Connection.SubmitRequest(HttpWebRequest request, Boolean forcedsubmit)
   at System.Net.ServicePoint.SubmitRequest(HttpWebRequest request, String connName)
   at System.Net.HttpWebRequest.SubmitRequest(ServicePoint servicePoint)
   at System.Net.HttpWebRequest.GetRequestStream(TransportContext& context)
   at System.Net.HttpWebRequest.GetRequestStream()
   .
   .(My function calls stack trace)
   .
   .

我试图解决这个问题的改变如下:

   <behavior>
    <serviceThrottling maxConcurrentCalls="2000"
                                 maxConcurrentInstances ="2400"
                                 maxConcurrentSessions ="400"/>
    </behavior>

在 web.config 中

<system.web>
        <compilation debug="false" />
        <httpRuntime executionTimeout="1800"/>
    </system.web>

在 web.config 中

  <system.net>
        <connectionManagement>
          <add address = "*" maxconnection = "100" />
        </connectionManagement>
      </system.net>

在 web.config 中

ServicePointManager.DefaultConnectionLimit = 100; (Change in code)

我已按照 StackOverflow 上许多人的建议将应用程序池的 IdleTimeout 属性设置为 0。

无论何时使用流,我都会在所有地方进行处理。所以所有的流都关闭了。

谁能告诉我谁在中止线程以及为什么以及是否有任何方法或工具来追踪线程中止启动的原因?

【问题讨论】:

  • 客户端是否有可能中止请求,导致服务器端也会产生异常
  • ASP.NET 会根据需要随时生成和终止工作进程。您的线程可能刚刚被 ASP.NET 关闭。找出您的计算机上可以同时运行多少个线程。还要尝试在测试期间跟踪处理器性能。
  • 您增加了池调用的数量,但没有增加缓冲区大小。我感觉有很多电话因此而被挂断。
  • 哪个服务正在记录错误?客户端服务还是 WCF 服务?

标签: c# wcf threadabortexception thread-abort


【解决方案1】:

我遇到了这个问题,它归结为对客户端类的使用不当。

发生的情况是,当客户端类被实例化时,它不会释放资源,从而导致吞吐量降低。会发生一个非常无用的异常“线程被中止”。通过创建一个 generic 同理创建客户端对象然后正确实现构造函数和 dispose 方法的帮助类来解决这个问题。

一些 IIS 异常对问题的实际原因没有多大帮助或真实性,但要深入了解为解决我的问题所做的工作是查看 IIS 日志。特别是“Failed Request Tracing Rules

希望这会有所帮助,我能理解您的沮丧,这是一个令人头疼的问题。

【讨论】:

    【解决方案2】:

    我以前也遇到过同样的事情。解决方案是通过实现 Dispose 方法在其范围结束后释放资源/客户端。

    存在问题,因为 C# using 语句在使用类型化客户端时自动清理资源不成功,并且抛出的任何异常都被隐式 dispose 掩盖,隐式 dispose 吃掉实际异常并抛出一些其他异常,如超时或其他异常。

    C#“使用”语句导致调用 Dispose()。这和Close()一样,发生网络错误时可能会抛出异常。因为对 Dispose() 的调用隐式发生在“using”块的右大括号处,所以编写代码和阅读代码的人都可能不会注意到这个异常源。这代表了应用程序错误的潜在来源。 (来自MSDN

    您应该释放资源,例如:

    try
    {
        ...
        client.Close();
    }
    catch (CommunicationException e)
    {
        ...
        client.Abort();
    }
    catch (TimeoutException e)
    {
        ...
        client.Abort();
    }
    catch (Exception e)
    {
        ...
        client.Abort();
        throw;
    }
    

    通过这种方式,您不仅可以找到异常的实际来源,还可以在发生某些执行时释放资源。

    其他替代解决方案可以实现Dispose,例如:

    /// <summary>
    /// Calculator Client
    /// </summary>
    public partial class CalculatorClient : IDisposable
    {
        #region IDisposable implementation
    
        /// <summary>
        /// IDisposable.Dispose implementation, calls Dispose(true).
        /// </summary>
        void IDisposable.Dispose()
        {
            Dispose(true);
        }
    
        /// <summary>
        /// Dispose worker method. Handles graceful shutdown of the
        /// client even if it is an faulted state.
        /// </summary>
        /// <param name="disposing">Are we disposing (alternative
        /// is to be finalizing)</param>
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                try
                {
                    if (State != CommunicationState.Faulted)
                    {
                        Close();
                    }
                }
                finally
                {
                    if (State != CommunicationState.Closed)
                    {
                        Abort();
                    }
                }
            }
        }
    
        /// <summary>
        /// Finalizer.
        /// </summary>
        CalculatorClient()
        {
            Dispose(false);
        }
    
        #endregion
    }
    

    来源

    Avoiding Problems with the Using StatementMSDN

    Using and Disposing of WCF Clients

    【讨论】:

    • 抱歉回复延迟。非常感谢你们的时间。由于我希望尽快解决问题,因此一种解决方法是增加解决问题的机器的内存大小。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-06-13
    • 2011-04-18
    • 1970-01-01
    • 1970-01-01
    • 2010-12-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多