Mamy aplikację, która ma usługę WCF (* .svc) działającą w usługach IIS7 i różnych klientów wysyłających zapytania do usługi. Na serwerze działa Win 2008 Server. Klienci korzystają z systemu Windows 2008 Server lub Windows 2003 Server. Otrzymuję następujący wyjątek, który, jak widziałem, może być w rzeczywistości powiązany z dużą liczbą potencjalnych problemów z WCF.
System.TimeoutException: The request channel timed out while waiting for a reply after 00:00:59.9320000. Increase the timeout value passed to the call to Request or increase the SendTimeout value on the Binding. The time allotted to this operation may have been a portion of a longer timeout. ---> System.TimeoutException: The HTTP request to 'http://www.domain.com/WebServices/myservice.svc/gzip' has exceeded the allotted timeout of 00:01:00. The time allotted to this operation may have been a portion of a longer timeout.
Zwiększyłem limit czasu do 30 minut, a błąd nadal występował. To mówi mi, że dzieje się coś innego, ponieważ przesłanie lub pobranie takiej ilości danych nigdy nie zajęłoby 30 minut.
Błąd pojawia się i znika. W tej chwili jest to częstsze. Wydaje się, że nie ma znaczenia, czy mam 3 klientów działających jednocześnie, czy 100, to nadal występuje od czasu do czasu. Przez większość czasu nie ma limitów czasu, ale wciąż dostaję kilka na godzinę. Błąd pochodzi z dowolnej wywoływanej metody. Jedna z tych metod nie ma parametrów i zwraca trochę danych. Inny pobiera wiele danych jako parametr, ale jest wykonywany asynchronicznie. Błędy zawsze pochodzą od klienta i nigdy nie odwołują się do żadnego kodu na serwerze w śladzie stosu. Zawsze kończy się:
at System.Net.HttpWebRequest.GetResponse()
at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
Na serwerze: próbowałem (i obecnie mam) następujące ustawienia powiązań:
maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" maxBufferPoolSize="2147483647"
Wydaje się, że nie ma to wpływu.
Próbowałem (i obecnie mam) następujące ustawienia ograniczania przepustowości:
<serviceThrottling maxConcurrentCalls="1500" maxConcurrentInstances="1500" maxConcurrentSessions="1500"/>
Wydaje się, że nie ma to wpływu.
Obecnie mam następujące ustawienia usługi WCF.
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]
Biegałem ConcurrencyMode.Multiple
przez chwilę, a błąd nadal występował.
Próbowałem ponownie uruchomić IIS, zrestartować mój bazowy SQL Server, zrestartować maszynę. Wszystko to wydaje się nie mieć wpływu.
Próbowałem wyłączyć zaporę systemu Windows. Wydaje się, że nie ma to wpływu.
Na kliencie mam takie ustawienia:
maxReceivedMessageSize="2147483647"
<system.net>
<connectionManagement>
<add address="*" maxconnection="16"/>
</connectionManagement>
</system.net>
Mój klient zamyka swoje połączenia:
var client = new MyClient();
try
{
return client.GetConfigurationOptions();
}
finally
{
client.Close();
}
Zmieniłem ustawienia rejestru, aby umożliwić więcej połączeń wychodzących:
MaxConnectionsPerServer=24, MaxConnectionsPer1_0Server=32.
Niedawno wypróbowałem SvcTraceViewer.exe. Udało mi się złapać jeden wyjątek po stronie klienta. Widzę, że trwa 1 minutę. Patrząc na ślad po stronie serwera, widzę, że serwer nie jest świadomy tego wyjątku. Maksymalny czas trwania, jaki widzę, to 10 sekund.
Przyjrzałem się aktywnym połączeniom z bazą danych używającym exec sp_who
na serwerze. Mam tylko kilka (2-3). Przyjrzałem się połączeniom TCP od jednego klienta za pomocą TCPview. Zwykle jest to około 2-3, a widziałem do 5 lub 6.
Mówiąc najprościej, jestem zaskoczony. Próbowałem wszystkiego, co mogłem znaleźć, i chyba brakuje mi czegoś bardzo prostego, co mógłby zobaczyć ekspert WCF. Mam przeczucie, że coś blokuje moich klientów na niskim poziomie (TCP), zanim serwer faktycznie otrzyma wiadomość i / lub że coś ustawia wiadomości w kolejce na poziomie serwera i nigdy nie pozwala im przetwarzać.
Jeśli masz jakieś liczniki wydajności, którym powinienem się przyjrzeć, daj mi znać. (proszę wskazać, które wartości są złe, ponieważ niektóre z tych liczników są trudne do rozszyfrowania). Ponadto, jak mogę zarejestrować rozmiar komunikatu WCF? Wreszcie, czy są tam jakieś narzędzia, które pozwoliłyby mi przetestować, ile połączeń mogę nawiązać między moim klientem a serwerem (niezależnie od mojej aplikacji)
Dziękuję za Twój czas!
Dodatkowe informacje dodane 20 czerwca:
Moja aplikacja WCF robi coś podobnego do następującego.
while (true)
{
Step1GetConfigurationSettingsFromServerViaWCF(); // can change between calls
Step2GetWorkUnitFromServerViaWCF();
DoWorkLocally(); // takes 5-15minutes.
Step3SendBackResultsToServerViaWCF();
}
Korzystając z WireShark, zauważyłem, że gdy wystąpi błąd, mam pięć retransmisji TCP, a następnie resetowanie TCP później. Domyślam się, że RST pochodzi z WCF zabijającego połączenie. Raport wyjątków, który otrzymuję, pochodzi z przekroczenia limitu czasu kroku 3.
Odkryłem to, patrząc na strumień tcp „tcp.stream eq 192”. Następnie rozszerzyłem mój filtr do „tcp.stream eq 192 i http i http.request.method eq POST” i zobaczyłem 6 wpisów POST podczas tego strumienia. Wydawało się to dziwne, więc sprawdziłem z innym strumieniem, takim jak tcp.stream eq 100. Miałem trzy posty POST, co wydaje się nieco bardziej normalne, ponieważ wykonuję trzy wywołania. Jednak zamykam połączenie po każdym wywołaniu WCF, więc spodziewałbym się jednego wywołania na strumień (ale nie wiem zbyt wiele o TCP).
Badając nieco więcej, zrzuciłem ładowanie pakietu HTTP na dysk, aby sprawdzić, gdzie te sześć wywołań.
1) Step3
2) Step1
3) Step2
4) Step3 - corrupted
5) Step1
6) Step2
Domyślam się, że dwóch równoczesnych klientów używa tego samego połączenia, dlatego widziałem duplikaty. Jednak wciąż mam kilka innych problemów, których nie mogę zrozumieć:
a) Dlaczego pakiet jest uszkodzony? Losowy błąd sieciowy - może? Ładunek jest zgzipowany przy użyciu tego przykładowego kodu: http://msdn.microsoft.com/en-us/library/ms751458.aspx - Czy kod może czasami zawierać błędy, jeśli jest używany jednocześnie? Powinienem testować bez biblioteki gzip.
b) Dlaczego miałbym zobaczyć kroki 1 i 2 uruchomione PO przekroczeniu limitu czasu uszkodzonej operacji? Wydaje mi się, że te operacje nie powinny były mieć miejsca. Może nie patrzę na właściwy strumień, ponieważ moje rozumienie TCP jest błędne. Mam inne strumienie, które pojawiają się w tym samym czasie. Powinienem zbadać inne strumienie - szybki rzut oka na strumienie 190-194 pokazują, że Step3 POST ma prawidłowe dane ładunku (nie są uszkodzone). Popycha mnie, bym ponownie spojrzał na bibliotekę gzip.