Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Ten artykuł ułatwia rozwiązanie błędu, który występuje, gdy usługa Windows Communication Foundation (WCF) może być skalowana powoli w górę pod obciążeniem.
Oryginalna wersja produktu: Windows Communication Foundation
Oryginalny numer KB: 2538826
Symptomy
Gdy usługa WCF odbiera serię żądań, domyślna pula wątków we/wy (IOCP) platformy .NET może nie być skalowana w górę tak szybko, jak to konieczne, a czas odpowiedzi programu WCF wzrośnie w wyniku. W zależności od czasu wykonania i liczby odebranych żądań można zauważyć liniowy wzrost czasu wykonywania WCF o około 500 ms dla każdego odebranego żądania, dopóki proces nie utworzył wystarczające wątki IOCP do obsługi żądań lub utrzymania obciążenia przychodzącego. Problem jest bardziej widoczny w usługach z dłuższym czasem wykonywania. Problem ze skalowalnością puli wątków IOCP nie jest zwykle obserwowany podczas początkowego ładowania procesu.
Przyczyna
Trzy zmienne, które mają wpływ na zdolność usługi WCF do skalowania w górę z niemal taką samą szybkością jak żądania przychodzące.
Ograniczanie przepustowości programu WCF
Wartość środowiska CLR
Threadpool.GetMinThreads
platformy .NETUsterka puli wątków IOCP środowiska .NET CLR, w której wątki IOCP nie są już tworzone we wzorcu odpowiadającym woluminowi żądań przychodzących przed wartością
Threadpool.GetMinThreads
ograniczania przepustowości.
W tym artykule opisano sposób rozwiązywania problemu z pulą wątków IOCP platformy .NET , #3. Jeśli masz problemy z ograniczaniem przepustowości spowodowane ograniczaniem przepustowości programu WCF lub GetMinThreads
wartością, to rozwiązanie nie pozwoli uniknąć tych ograniczń. Zobacz sekcję Więcej informacji poniżej, aby uzyskać wskazówki dotyczące identyfikowania scenariusza. Usterka tworzenia wątku IOCP powinna zostać rozwiązana w następnym wpisie 4.0 programu .NET Framework. Ten problem z skalowalnością nie istnieje w puli wątków procesu roboczego środowiska .NET CLR.
Rozwiązanie
Przeniesienie wykonywania usługi WCF do innej puli wątków może spowodować niewielkie obciążenie związane z implementacją tego rozwiązania. Wyniki wydajności będą się różnić w zależności od usługi WCF. Przetestuj każdą usługę WCF, aby uzyskać poszczególne wyniki.
Uwaga 16.
Zastosuj to rozwiązanie podczas korzystania z odbiornika WCF, który nie blokuje przychodzącego wątku podczas oczekiwania na ukończenie kodu usługi WCF.
Odbiornik WCF | Zalecane rozwiązanie |
---|---|
Moduł synchronizacji HTTP (domyślny w wersji 3.x) — używany w zintegrowanej puli aplikacji | Przejdź do programu obsługi asynchronicznego, a następnie zastosuj rozwiązanie w tym artykule lub możesz użyć puli wątków prywatnych. (zobacz linki poniżej tej tabeli) |
Moduł asynchroniczny HTTP (domyślnie w wersji 4.x) — używany w zintegrowanej puli aplikacji | Zastosuj rozwiązanie kodu w tym artykule. |
ISAPI — używany w puli aplikacji w trybie klasycznym | Zastosuj pulę wątków prywatnych. (zobacz linki poniżej tej tabeli) |
tcp.Net |
Zastosuj rozwiązanie kodu w tym artykule. |
Jeśli nie możesz zastosować rozwiązania w tym artykule poniżej powyższej tabeli, przykład użycia puli wątków prywatnych można znaleźć w artykule MSDN: Foundations: Synchronization Contexts in WCF (Podstawy: konteksty synchronizacji w programie WCF).
Kroki implementowania tego rozwiązania, które spowoduje wykonanie usługi WCF w puli wątków procesu roboczego środowiska CLR platformy .NET:
Progi ograniczania WCF powinny być wystarczająco wysokie, aby obsłużyć oczekiwany wolumin wybuchu w akceptowalnych czasach odpowiedzi.
Jeśli używasz jednej z domyślnych pul wątków środowiska .NET CLR, Procesu roboczego lub IOCP dla usługi WCF, musisz upewnić się, że minimalna liczba wątków (wartość, w której rozpoczyna się ograniczanie tworzenia wątków) do liczby, którą przewidujesz wykonać jednocześnie.
Zaimplementuj następujący kod w usłudze, który następnie wykona usługę WCF w puli wątków procesu roboczego środowiska CLR platformy .NET.
Ta klasa służy do przenoszenia wykonywania do puli wątków procesu roboczego ŚRODOWISKA CLR platformy .NET.
public class WorkerThreadPoolSynchronizer : SynchronizationContext { public override void Post(SendOrPostCallback d, object state) { // WCF almost always uses Post ThreadPool.QueueUserWorkItem(new WaitCallback(d), state); } public override void Send(SendOrPostCallback d, object state) { // Only the peer channel in WCF uses Send d(state); } }
Następnie musimy utworzyć klasę atrybutów niestandardowych.
[AttributeUsage(AttributeTargets.Class)] public class WorkerThreadPoolBehaviorAttribute : Attribute, IContractBehavior { private static WorkerThreadPoolSynchronizer synchronizer = new WorkerThreadPoolSynchronizer(); void IContractBehavior.AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { } void IContractBehavior.ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime) { } void IContractBehavior.ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime) { dispatchRuntime.SynchronizationContext = synchronizer; } void IContractBehavior.Validate(ContractDescription contractDescription, ServiceEndpoint endpoint) { } }
Teraz, aby zastosować atrybut niestandardowy do usługi WCF. Przykład:
[WorkerThreadPoolBehavior] public class Service1 : IService1 { public string GetData(int value) { int iSleepSec = (value * 1000); System.Threading.Thread.Sleep(iSleepSec); return string.Format("You slept for: {0} seconds", value); } }
Więcej informacji
WCF używa puli wątków środowiska .NET CLR IOCP do wykonywania kodu usługi WCF. Problem występuje, gdy pula wątków IOCP środowiska .NET CLR wchodzi w stan, w którym nie można szybko utworzyć wątków wystarczająco szybko, aby natychmiast obsłużyć serię żądań. Czas odpowiedzi wzrasta nieoczekiwanie, ponieważ nowe wątki są tworzone z szybkością 1 na 500 ms.
Problem może stać się bardziej oczywisty, jeśli usługa WCF korzysta z technologii, która również korzysta z puli wątków IOCP środowiska .NET CLR. Na przykład klient pamięci podręcznej appFabric systemu Windows Server korzysta z tej puli wątków w niewielkim stopniu.
Jeśli nie osiągniesz opisanych wcześniej limitów ograniczania przepustowości WCF, poniższe informacje pomogą Ci określić, czy występuje problem z pulą wątków IOCP środowiska .NET CLR.
Pule wątków środowiska .NET CLR używają wartości do określenia, kiedy rozpocząć ograniczanie tworzenia wątków. To ustawienie można określić przez wywołanie metody ThreadPool.GetMinThreads(Int32, Int32) lub podczas analizowania zrzutu procesu przy użyciu narzędzia ! Rozszerzenie debugera SOS SOS.dll (rozszerzenie debugowania SOS).
0:000> ! C:\windows\Microsoft.NET\Framework64\v4.0.30319\sos.threadpool
Wykorzystanie procesora CPU: 0%
Wątek procesu roboczego: Łącznie: 16 Uruchomione: 0 Bezczynność: 16 MaxLimit: 250 MinLimit: 125
Żądanie pracy w kolejce: 0
Liczba czasomierzy: 35
Wątek portu ukończenia: Łącznie: 26 Free: 0 MaxFree: 16 CurrentLimit: 28 MaxLimit: 1000 MinLimit: 125
Zaobserwowany problem występuje, gdy pula wątków środowiska .NET CLR IOCP wprowadza warunek, w którym nowy wątek jest tworzony tylko co 500 ms (dwa na sekundę) przed wartością MinLimit puli wątków dla puli wątków. Inne oczekiwane czynniki, które mogą również przyczynić się do opóźnienia tworzenia wątku, to wykorzystanie pamięci lub wysokie użycie procesora CPU.
Monitoruj proces hostowania usługi WCF. Jeśli zauważysz problem ze skalowaniem wątków w górę przed ustawionymi minimalnymi progami, może wystąpić problem z pulą wątków środowiska .NET CLR IOCP. Aby określić, czy tak jest, wydajność powinna być używana do monitorowania współczynnika tworzenia wątku procesu w porównaniu z szybkością żądań przychodzących. Aby to osiągnąć, zarejestruj lub wyświetl następujące liczniki wydajności (poniżej znajduje się przykład usługi IIS (WAS) hostowanej w programie WCF 4.0 przy użyciu powiązania HTTP):
Licznik | Wystąpienia |
---|---|
Liczba procesów/wątków | Wszystkie wystąpienia W3WP(x) |
Kolejki żądań obsługi HTTP / szybkość przylotu | <Pula aplikacji hostująca usługi WCF> |
ASP.NET Apps v(4 lub 2) / Żądania wykonywane | <Wystąpienia aplikacji WCF> |
ASP.NET Apps v(4 lub 2) / Czas wykonywania żądania | <Wystąpienia aplikacji WCF> |
Możesz również użyć liczników wydajności programu WCF, jeśli są one włączone:
Liczniki wydajności programu WCF
Normalne jest, aby zobaczyć powoli rosnącą liczbę wątków, gdy częstotliwość przylotu (wzorzec żądań klientów) jest następująca zgodnie z tym samym wzorcem. Jest to tylko wtedy, gdy występuje natychmiastowy skok żądań przychodzących, a liczba wątków powoli wzrasta z szybkością dwóch wątków na sekundę, podczas gdy czas odpowiedzi programu WCF zwiększa się, że istnieje problem.
Ten zrzut ekranu przedstawia proces roboczy, który po pewnym czasie napotkał problem ze skalowalnością puli wątków IOCP platformy .NET. Po pierwszym uruchomieniu procesu wątki IOCP są zwykle tworzone równolegle do obciążenia żądania przychodzącego. W tej puli aplikacji (W3WP.EXE) uruchomiono dwie usługi WCF. Jedna usługa używała domyślnej puli wątków IOCP platformy .NET, która otrzymała serię 100 żądań o godzinie 10:22:14 i ponownie o godzinie 10:23:34. Druga usługa WCF używała powyższego obejścia do wykonania w puli wątków procesu roboczego platformy .NET i odebrała serię 100 żądań o godzinie 10:22:54. Po wprowadzeniu tego stanu proces jest wymagany do przywrócenia puli wątków IOCP do działającego, skalowalnego stanu.