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.
źródło
Odpowiedzi:
Jeśli używasz klienta .Net, być może nie ustawiłeś
//This says how many outgoing connection you can make to a single endpoint. Default Value is 2 System.Net.ServicePointManager.DefaultConnectionLimit = 200;
Oto oryginalne pytanie i odpowiedź Ograniczanie usługi WCF
Aktualizacja :
Ta konfiguracja jest umieszczana w aplikacji klienta .Net może być podczas uruchamiania lub kiedykolwiek, ale przed rozpoczęciem testów.
Ponadto możesz go mieć w pliku app.config, a także w następujący sposób
<system.net> <connectionManagement> <add maxconnection = "200" address ="*" /> </connectionManagement> </system.net>
źródło
Jeśli jeszcze tego nie próbowałeś - hermetyzuj operacje WCF po stronie serwera w blokach try / Final i Dodaj rejestrowanie, aby upewnić się, że faktycznie zwracają.
Jeśli pokażą, że operacje się kończą, następnym krokiem byłoby zejście na niższy poziom i przyjrzenie się rzeczywistej warstwie transportowej.
W tym momencie bardzo pomocny może być program Wireshark lub inne podobne narzędzie do przechwytywania pakietów. Zakładam, że działa to przez HTTP na standardowym porcie 80.
Uruchom Wireshark na kliencie. W Opcjach po rozpoczęciu przechwytywania ustaw filtr przechwytywania na
tcp http and host service.example.com
- zmniejszy to ilość nieistotnego ruchu.Jeśli możesz, zmodyfikuj swojego klienta, aby powiadomił Cię o dokładnym czasie rozpoczęcia połączenia oraz o czasie, kiedy upłynął limit czasu. Albo po prostu uważnie to obserwuj.
Gdy pojawi się błąd, możesz przeszukać dzienniki Wireshark, aby znaleźć początek połączenia. Kliknij prawym przyciskiem myszy pierwszy pakiet, który wywołuje Twój klient (powinno to być coś w rodzaju GET /service.svc lub POST /service.svc) i wybierz Śledź strumień TCP.
Wireshark zdekoduje całą konwersację HTTP, dzięki czemu możesz upewnić się, że WCF faktycznie odsyła odpowiedzi.
źródło
od: http://www.codeproject.com/KB/WCF/WCF_Operation_Timeout_.aspx
źródło
Mam bardzo podobny problem. W przeszłości było to związane z problemami z serializacją. Jeśli nadal masz ten problem, czy możesz sprawdzić, czy możesz poprawnie serializować zwracane obiekty. W szczególności, jeśli używasz obiektów Linq-To-Sql, które mają relacje, istnieją znane problemy z serializacją, jeśli umieścisz odwołanie wsteczne na obiekcie podrzędnym w obiekcie nadrzędnym i oznaczysz to odwołanie wsteczne jako DataMember.
Możesz zweryfikować serializację, pisząc aplikację konsolową, która serializuje i deserializuje obiekty przy użyciu DataContractSerializer po stronie serwera i wszelkich metod serializacji używanych przez klienta. Na przykład w naszej obecnej aplikacji mamy klientów zarówno WPF, jak i Compact Framework. Napisałem aplikację konsolową, aby sprawdzić, czy mogę serializować za pomocą DataContractSerializer i deserializować za pomocą XmlDesserializer. Możesz tego spróbować.
Ponadto, jeśli zwracasz obiekty Linq-To-Sql, które mają kolekcje podrzędne, możesz spróbować upewnić się, że chętnie ładowałeś je po stronie serwera. Czasami z powodu leniwego ładowania zwracane obiekty nie są zapełniane i mogą powodować zachowanie, które widzisz, gdy żądanie jest wysyłane do metody usługi wiele razy.
Jeśli rozwiązałeś ten problem, chciałbym usłyszeć, jak to zrobić, ponieważ ja też z tym utknąłem. Po sprawdzeniu, że mój problem nie dotyczy serializacji, jestem zagubiony.
AKTUALIZACJA: Nie jestem pewien, czy to ci pomoże, ale narzędzie Service Trace Viewer właśnie rozwiązało mój problem po 5 dniach bardzo podobnego doświadczenia do twojego. Konfigurując śledzenie, a następnie przeglądając nieprzetworzony kod XML, znalazłem wyjątki, które powodowały problemy z serializacją. Był powiązany z obiektami Linq-to-SQL, które czasami miały więcej obiektów podrzędnych, niż można było z powodzeniem serializować. Dodanie następujących elementów do pliku web.config powinno umożliwić śledzenie:
<sharedListeners> <add name="sharedListener" type="System.Diagnostics.XmlWriterTraceListener" initializeData="c:\Temp\servicetrace.svclog" /> </sharedListeners> <sources> <source name="System.ServiceModel" switchValue="Verbose, ActivityTracing" > <listeners> <add name="sharedListener" /> </listeners> </source> <source name="System.ServiceModel.MessageLogging" switchValue="Verbose"> <listeners> <add name="sharedListener" /> </listeners> </source> </sources>
Wynikowy plik można otworzyć za pomocą narzędzia Service Trace Viewer lub po prostu w przeglądarce IE, aby sprawdzić wyniki.
źródło
Czy zamykasz połączenie z usługą WCF między żądaniami? Jeśli tego nie zrobisz, zobaczysz dokładny limit czasu (ostatecznie).
źródło
Właśnie rozwiązałem problem, stwierdziłem, że węzły w pliku App.config są źle skonfigurowane.
<client> <endpoint name="WCF_QtrwiseSalesService" binding="wsHttpBinding" bindingConfiguration="ws" address="http://cntgbs1131:9005/MyService/TGE.ISupplierClientManager" contract="*"> </endpoint> </client> <bindings> <wsHttpBinding> <binding name="ws" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" messageEncoding="Text"> <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/> <**security mode="None">** <transport clientCredentialType="None"></transport> </security> </binding> </wsHttpBinding> </bindings>
Potwierdź konfigurację w węźle
<security>
, wartość atrybutu „tryb” to „Brak”. Jeśli wartością jest „Transport”, wystąpi błąd.źródło
Czy próbowałeś użyć clientVia, aby zobaczyć wysłaną wiadomość, używając zestawu narzędzi SOAP lub czegoś podobnego? Może to pomóc sprawdzić, czy błąd pochodzi od samego klienta, czy z innego miejsca.
źródło
deprecated
Czy sprawdziłeś ślady WCF? WCF ma tendencję do połykania wyjątków i zwracania tylko ostatniego wyjątku, czyli limitu czasu, który otrzymujesz, ponieważ punkt końcowy nie zwrócił nic sensownego.
źródło
Ten błąd zostanie również wyświetlony, jeśli przekazujesz klientowi obiekt, który zawiera właściwość typu enum, która nie jest ustawiona domyślnie, a wyliczenie nie ma wartości odwzorowanej na 0. tj.
enum MyEnum{ a=1, b=2};
źródło
Wygląda na to, że ten komunikat o wyjątku jest dość ogólny i może zostać odebrany z różnych powodów. Napotkaliśmy to podczas wdrażania klienta na komputerach z systemem Windows 8.1. Nasz klient WCF działa w usłudze systemu Windows i stale sonduje usługę WCF. Usługa systemu Windows działa na koncie użytkownika innego niż administrator. Problem został rozwiązany przez ustawienie clientCredentialType na „Windows” w konfiguracji WCF, aby umożliwić uwierzytelnianie do przekazywania, jak w następującym:
<security mode="None"> <transport clientCredentialType="Windows" proxyCredentialType="None" realm="" /> <message clientCredentialType="UserName" algorithmSuite="Default" /> </security>
źródło
Nie jestem ekspertem od WCF, ale zastanawiam się, czy nie korzystasz z ochrony DDOS w usługach IIS. Z doświadczenia wiem, że jeśli uruchomisz kilka jednoczesnych połączeń od pojedynczego klienta do serwera, w pewnym momencie serwer przestanie odpowiadać na wywołania, ponieważ podejrzewa atak DDOS. Utrzyma również otwarte połączenia do czasu ich przekroczenia, aby spowolnić ataki klienta.
Wielokrotne połączenia pochodzące z różnych komputerów / adresów IP nie powinny jednak stanowić problemu.
Więcej informacji znajduje się w tym poście MSDN:
http://msdn.microsoft.com/en-us/library/bb463275.aspx
Sprawdź właściwość MaxConcurrentSession.
źródło