2011-05-09 14 views
5

Mamy duży proces w naszej aplikacji, który działa raz w miesiącu. Ten proces zazwyczaj trwa około 30 minut i generuje 342000 zdarzeń związanych z logowaniem. Niedawno zaktualizowaliśmy nasze logowanie do modelu scentralizowanego za pomocą WCF i obecnie mamy problemy z wydajnością. Podczas gdy poprzednie rozwiązanie zakończy się za około 30 minut, z nowym rejestrowaniem, zajmuje to teraz 3 lub 4 godziny. Problem wydaje się, ponieważ aplikacja faktycznie czeka na zakończenie żądania WCF przed wykonaniem. Metoda WCF jest już skonfigurowana jako IsOneWay i opakowałem wywołanie po stronie klienta do tej metody WCF w innym wątku, aby spróbować zapobiec tego typu problemom, ale wydaje się, że nie zadziałało. Myślałem o korzystaniu z asynchronicznych wywołań WCF, ale pomyślałem, zanim spróbowałem czegoś innego, o co prosiłbym tutaj, aby sprawdzić, czy istnieje lepszy sposób na poradzenie sobie z tym.Logowanie za pośrednictwem WCF bez spowalniania rzeczy w dół

+1

Nie można podać prawdziwej odpowiedzi, ale: Szukasz kolejki wiadomości. Istnieje Microsoft Message Queue jako część systemu Windows, lub jest NServiceBus i być może inne. Kolejka komunikatów pozwala twojemu aplikacjowi wysłać te pliki do lokalnej usługi (dzięki czemu twoja aplikacja nie grzęźnie w dół), a kolejka zajmuje się wysyłaniem wiadomości, obsługą błędów/ponownym próbą i tym wszystkim. Alternatywnie, wsadowe wywołania WCF. Nie rób połączeń dla każdej wiadomości, ale partię 100 i wyślij je za jednym razem. –

Odpowiedz

4

342000 zdarzeń log w ciągu 30 minut, jeśli zrobiłem poprawnie matematykę, wychodzi na 190 zdarzeń w dzienniku na sekundę. Myślę, że twój problem może dotyczyć domyślnych ustawień dławienia w WCF. Nawet jeśli twoja metoda jest ustawiona na opcję jednokierunkową, w zależności od tego, czy tworzysz nowe proxy dla każdego rejestrowanego zdarzenia, wywołanie metody będzie nadal blokować podczas tworzenia proxy, kanał zostanie otwarty i jeśli używasz Oparte na HTTP, będzie blokowane, dopóki wiadomość nie zostanie odebrana przez usługę (powiązanie oparte na HTTP odsyła odpowiedź null dla jednokierunkowego wywołania metody, gdy wiadomość zostanie odebrana). Domyślne ograniczanie WCF ogranicza równoległe instancje do 10 po stronie usługi, co oznacza, że ​​tylko 10 żądań będzie obsługiwanych naraz, a wszelkie dalsze żądania będą umieszczane w kolejce, więc sparuj je z powiązaniem HTTP i cokolwiek po pierwszych 10 żądaniach będzie blokował klienta, dopóki nie otrzyma jednego z 10 żądań. Nie wiedząc, jak skonfigurowane są twoje usługi (tryb instancji itp.), Trudno powiedzieć coś więcej, ale jeśli używasz wywoływania dla każdego połączenia, polecam ustawienie MaxConcurrentCalls i MaxConcurrentInstances na twoim ServiceBehavior na coś znacznie wyższego (wartości domyślne to odpowiednio 16 i 10).

Ponadto, aby oprzeć się na tym, co inni wspomnieli o agregowaniu wielu zdarzeń i przekazywaniu ich wszystkich naraz, uważam za pomocne ustawienie statycznej metody Logger.LogEvent(eventData). W ten sposób można go łatwo zastosować w całym kodzie, a także można kontrolować w metodzie LogEvent sposób zachowywania się logowania w aplikacji, na przykład konfigurowanie liczby zdarzeń, które powinny zostać przesłane w danym momencie.

+0

Dziękuję za odpowiedź. Początkowo koncentruję się na "wyślij i zapomnij". Zrzuć go na serwer i pozwól mu obsłużyć opad. Jeśli otrzymam komunikat o zrzuceniu wiadomości lub zatoru na serwerze, rozwiążę ten problem osobno. Zastanawiam się nad tym, dlaczego wysyłanie wiadomości na serwer w osobnym wątku wpływa na mój główny wątek? Rozumiem, że twoja uwaga jest skierowana na przekazywanie wiadomości w celu zwiększenia efektywności i może się to skończyć, ale czysto akademicko, dlaczego oddzielna nić nie izoluje mnie od tego spowolnienia? – omatase

+0

Trudno odpowiedzieć, nie wiedząc, w jaki sposób zaimplementowano oddzielny wątek. Jeśli jednak ma to związek z dławieniem, a wywołanie WCF jest znacznie droższe niż większość innych operacji, może to oznaczać, że ukończenie programu może zająć bardzo dużo czasu, jeśli tylko 10 żądania są obsługiwane w tym samym czasie. Czy istnieje sposób, aby stwierdzić, czy wszystko inne zostało ukończone, a twój program właśnie nadrabia zaległości w zgłoszeniach? Czy znaczniki czasu pochodzą od momentu zakończenia operacji lub kiedy jest ona rejestrowana? –

0

Zawsze jest tradycyjny syslog istnieje wiele demonów syslog, które działają w systemie Windows. Został zaprojektowany jako bardziej wydajny sposób scentralizowanego rejestrowania niż WCF, który jest przeznaczony do mniej intensywnych operacji, szczególnie jeśli nie korzystasz z konfiguracji tcpip WCF.

Innymi słowy, użyj tego - właściwego narzędzia do pracy.

3

Nawiązywanie połączenia z innym procesem lub usługą zdalną (np. Wywoływanie usługi WCF) jest najdroższą rzeczą, jaką można zrobić w aplikacji. Robienie tego 342,000 razy jest po prostu zwykłym szaleństwem!

Jeśli musisz zalogować się do scentralizowanej usługi, musisz zgromadzić partie wpisów w dzienniku, a następnie, tylko gdy powiesz w pamięci 1000 lub więcej, wyślij je wszystkie do usługi za jednym razem. Zapewni to rozsądną poprawę wydajności.

1

log4net ma system buforowania, który istnieje poza kontekstem wątku wywołującego, dzięki czemu nie będzie podtrzymywać połączenia podczas jego logowania. Jego użycie powinno być jasne z wielu appender config examples - wyszukiwanie terminu bufferSize. Jest używany na wielu powolnych aplikatorach (np. Remoting, e-mail), aby utrzymać wątek źródłowy w ruchu, nie czekając na wolniejszym nośniku rejestrowania, i istnieje również ogólny meta-appender buforujący, który może być używany "przed" jakikolwiek inny aplikant.

Używamy go z AdoNetAppender w systemie o podobnej pojemności i działa wspaniale.

Powiązane problemy