Исключения, прерванные потоком в службе wcf

#c# #wcf #threadabortexception #thread-abort

#c# #wcf ( ВКФ ) #исключение threadabortexception #прерывание потока

Вопрос:

У меня есть служба WCF (встроенная в .NET framework 3.5), размещенная на IIS 6.0.

Поток кода выглядит следующим образом

  1. Клиент (который является другим веб-сервисом) вызывает службу WCF
  2. Службы WCF вызывают поток для выполнения обработки в фоновом режиме и немедленно отвечают вызываемому.
  3. Фоновый поток после завершения всей обработки вызывает поток обратно. Этот вызов в основном представляет собой HTTPs-запрос, поскольку клиент является веб-сервисом.

Я провожу нагрузочное тестирование своего сервиса WCF, чтобы определить пороговые значения. Наблюдение заключается в следующем:

Около 3 итераций из 1024 запросов, отправленных в службу WCF в течение 1 минуты, проходят успешно. Время, затрачиваемое на выполнение каждой итерации, составляет около 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(TransportContextamp; 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)
  

Я установил свойству idleTimeout пула приложений значение 0, как предлагали многие пользователи StackOverflow.

Где бы ни использовались потоки, у меня есть dispose во всех местах. Таким образом, все потоки закрыты.

Кто-нибудь может сказать мне, кто прерывает потоки и почему, и есть ли какие-либо средства или инструмент для отслеживания причины инициирования прерывания потока?

Комментарии:

1. Возможно ли, что Клиент прерывает запрос, потому что это также сгенерирует исключение на стороне сервера

2. ASP.NET порождает и убивает рабочие процессы постоянно по мере необходимости. Возможно, ваш поток просто закрывается из-за ASP.NET . Узнайте, сколько потоков может быть запущено одновременно на вашем компьютере. Также попробуйте отследить производительность процессора во время тестирования.

3. Вы увеличили объем объединенных вызовов, но не увеличили размер буфера. У меня такое чувство, что из-за этого многие звонки прекращаются.

4. Какая служба регистрирует ошибку? Клиентская служба или служба WCF?

Ответ №1:

Я столкнулся с этой проблемой, и она была вызвана неправильным использованием клиентского класса.

Что происходило, так это то, что при создании экземпляра клиентского класса он не освобождал ресурсы обратно, что приводило к снижению пропускной способности. Возникло бы очень бесполезное исключение «Поток был прерван». Это было решено путем создания вспомогательного класса, который generically создал клиентский объект, а затем правильно реализовал конструктор и метод dispose.

Некоторые исключения IIS не очень полезны или соответствуют фактической причине проблемы, но чтобы разобраться в том, что было сделано для решения моей проблемы, нужно было просмотреть журналы IIS. В частности, «Правила отслеживания неудачных запросов«

Надеюсь, это поможет, я могу понять ваше разочарование, решить которое было головной болью.

Ответ №2:

Я уже сталкивался с тем же самым раньше. Решение состояло в том, чтобы освободить ресурсы / клиент после завершения его области действия путем реализации метода Dispose.

Проблема существует, поскольку инструкция C # using для автоматической очистки ресурсов при использовании типизированного клиента не выполняется успешно, и любое генерируемое исключение маскируется неявным dispose, который использует фактическое исключение и выдает какое-либо другое исключение, такое как тайм-аут или другие исключения.

Оператор C # «using» приводит к вызову 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
}
  

Источники :

Как избежать проблем с инструкцией Using MSDN

Использование и утилизация клиентов WCF

Комментарии:

1. Извините за задержку с ответом. Большое вам спасибо за уделенное время, ребята. Поскольку я хотел, чтобы проблема была устранена как можно скорее, одним из способов решения проблемы было увеличение размера оперативной памяти компьютера, который устранил проблему.