Поток прервал исключения в сервисе wcf
У меня есть служба WCF (встроенная в.NET Framework 3.5), размещенная на IIS 6.0.
Поток кода выглядит следующим образом
- Клиент (который является другим веб-сервисом) вызывает сервис WCF
- Службы WCF вызывают поток для выполнения обработки в фоновом режиме и немедленно отвечают на вызываемый объект.
- Фоновый поток после завершения всей обработки вызывает его обратно. Этот вызов в основном является запросом HTTP, поскольку клиент является веб-службой.
Я нагрузочно тестирую свой сервис WCF для определения пороговых значений. Наблюдение заключается в следующем:
Около 3 итераций из 1024 запросов к службе WCF в течение 1 минуты проходят успешно. Время, необходимое для завершения каждой итерации, составляет около 25-30 минут. Однако с 4-й итерации наблюдаются массовые сбои. Около 50% запросов не выполняются, за исключением следующего.
Exception-Thread был прерван.
Трассировки стека
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)
Я установил для свойства IdleTimeout пула приложений значение 0, как предлагают многие пользователи Stackru.
Где бы ни использовались потоки, я располагаю во всех местах. Так что все потоки закрыты.
Может ли кто-нибудь сказать мне, кто прерывает потоки и почему, и существуют ли какие-либо средства или средства для отслеживания причины инициации прерывания потока?
2 ответа
Я сталкивался с этой проблемой, и это было связано с неправильным использованием класса клиента.
Происходит следующее: когда создается экземпляр класса клиента, он не освобождает ресурсы обратно, что приводит к снижению пропускной способности. Может произойти очень бесполезное исключение "Поток был прерван". Это было решено путем создания вспомогательного класса, который в общем случае создавал клиентский объект, а затем правильно реализовывал конструктор и метод dispose.
Некоторые исключения IIS не очень полезны или не соответствуют истинной причине проблемы, но чтобы понять, что было сделано для решения моей проблемы, нужно было просмотреть журналы IIS. В частности, " Правила отслеживания невыполненных запросов"
Надеюсь, это поможет, я могу понять ваше разочарование, что решить проблему было головной болью.
Я сталкивался с тем же лицом раньше. Решение состояло в том, чтобы освободить ресурсы / клиента после того, как его область была закончена путем реализации метода 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
}
Источники: