Mamy do czynienia z interesującym problemem na StackOverflow.
Mamy całą masę drobnych „zadań do zrobienia wkrótce”. Przykładem jest aktualizacja list „Podobne pytania”. To, co zrobiliśmy w przeszłości, polega na nałożeniu tych zadań na obciążenia niektórych użytkowników.
To nigdy nie było idealne, ale tak naprawdę nie było zauważalne. Teraz, gdy SO przekroczyło 1 000 000 znaków zapytania, ci pechowi użytkownicy zaczynają to odczuwać.
Naturalnym rozwiązaniem jest przesunięcie tych zadań na drugi plan. Rozważam dwa szerokie sposoby na zrobienie tego.
1. W IIS jako niestandardowa pula wątków / kolejka robocza
Zasadniczo rozpakowujemy kilka wątków (innych niż ThreadPool , aby nie zakłócać IIS) i udostępniamy im niektóre kolekcje, w które wrzucamy Funcs .
Wielkim profesjonalistą jest tutaj prostota. Nie musimy się martwić o zbieranie niczego, ani nie musimy upewnić się, że niektóre usługi zewnętrzne działają i reagują.
Uzyskujemy również dostęp do całego naszego wspólnego kodu.
Wadą jest to, że nie powinniśmy używać wątków w tle. Zarzuty, o których wiem, koncentrują się wokół głodujących IIS (jeśli używasz ThreadPool), a wątki umierają losowo (z powodu recyklingu AppPool).
Mamy istniejącą infrastrukturę, dzięki której losowa śmierć wątku nie będzie problemem (w zasadzie możliwe jest wykrycie zadania, które zostało porzucone), a ograniczenie liczby wątków (i używanie wątków innych niż ThreadPool) również nie jest trudne.
Przeniesiony do StackOverflow , ponieważ tak naprawdę nie został tutaj rozwiązany.
2. Jako usługa
Albo jakieś rozwiązanie innej firmy, albo niestandardowe.
Zasadniczo zorganizujemy zadanie przekraczające granicę procesu do jakiejś usługi i po prostu o tym zapomnimy. Przypuszczalnie łączymy jakiś kod lub ograniczamy się do surowego SQL + ciąg połączenia.
Zaletą jest to, że jest to „właściwy sposób”, aby to zrobić.
Wadami są to, że albo jesteśmy bardzo ograniczeni w tym, co możemy zrobić, albo będziemy musieli wypracować jakiś system, aby utrzymać tę usługę w synchronizacji z naszą bazą kodu. Będziemy też musieli jakoś przechwycić wszystkie nasze monitorowanie i rejestrowanie błędów, które otrzymujemy za darmo z opcją „In IIS”.
Czy są jakieś inne korzyści lub problemy z podejściem serwisowym?
W skrócie, czy istnieją nieprzewidziane i nie do pokonania problemy, które sprawiają, że podejście nr 1 jest niewykonalne, a jeśli tak, to czy są jakieś dobre usługi stron trzecich, na które powinniśmy zwrócić uwagę w kierunku podejścia nr 2?
źródło
Odpowiedzi:
Kilka tygodni temu zadałem podobne pytanie dotyczące SO. W skrócie, moje podejście od pewnego czasu polega na opracowaniu usługi Windows. Korzystałbym z NServiceBus (zasadniczo MSMQ pod przykryciem), aby kierować żądania z mojej aplikacji internetowej do mojego serwisu. Kiedyś korzystałem z WCF, ale uzyskanie rozproszonej transakcji do prawidłowego działania w WCF zawsze wydawało się bólem w tyłek. NServiceBus załatwił sprawę, mogłem zatwierdzać dane i tworzyć zadania w transakcji i nie martw się, czy moja usługa była wtedy uruchomiona. Jako prosty przykład, jeśli kiedykolwiek będę musiał wysłać wiadomość e-mail (na przykład e-mail rejestracyjny), utworzę konto użytkownika i wystrzelę sygnał do mojej usługi Windows (aby wysłać wiadomość e-mail) w transakcji. Procedura obsługi komunikatów po stronie usługi odbierze komunikat i odpowiednio przetworzy.
Od czasu wydania ASP .NET 4.0 i AppFabric istnieje wiele realnych alternatyw dla powyższego mechanizmu. Nawiązując do pytania, które wspomniałem powyżej, mamy teraz AppFabric AppInitialize (przez net.pipe), a także funkcję automatycznego uruchamiania ASP .NET 4.0, która sprawia, że tworzenie usług Windows jako aplikacji internetowych jest realną alternatywą. Zacząłem to robić teraz z wielu powodów (największym z nich jest to, że wdrożenie nie jest już problemem w dupie):
Jeśli pójdziesz tą drogą (wybacz mi kopiowanie i wklejanie z mojego oryginalnego postu) zdecydowanie rozważę uruchomienie logiki w tle w osobnej aplikacji internetowej. Istnieje wiele powodów:
W ten sposób wracam do aspektu marszałkowskiego. WCF, NServiceBus / RabbitMQ / ActiveMQ itp., Waniliowy MSMQ, RESTful API (pomyśl MVC) to wszystkie opcje. Jeśli używasz systemu Windows Workflow 4.0, możesz ujawnić punkt końcowy hosta, z którego może korzystać Twoja aplikacja internetowa.
Podejście do hostingu usług jest wciąż dla mnie dość nowe, dopiero czas pokaże, czy był to właściwy wybór. Jak dotąd tak dobrze. Nawiasem mówiąc, jeśli nie chcesz używać AppFabric (nie mogłem, bo z jakiegoś dziwnego powodu Windows Server Web Edition nie jest obsługiwany), funkcja Auto-Start wspomniana w poście Gu działa dobrze. Trzymaj się z dala od pliku applicationhost.config, wszystko w tym poście można skonfigurować za pomocą konsoli IIS (Edytor konfiguracji na poziomie głównego serwera).
Uwaga: pierwotnie zamieściłem kilka innych linków w tej wiadomości, ale niestety, to mój pierwszy post na tej wymianie i obsługiwany jest tylko jeden link! Były w zasadzie dwa inne, aby uzyskać od Google „Śmierć usługom systemu Windows ... Long Live AppFabric!” oraz „aplikacje auto-start-asp-net”. Przepraszam za to.
źródło
W rzeczywistości system Windows oferuje trzeci sposób uruchamiania usług w tle i jest bardzo powszechny w świecie UNIX. Trzeci sposób to
CRON
zadanie polegające na uruchomieniu części infrastruktury. W systemie Windows jest to znane jakotask scheduler
bardzo częste uruchamianie kodu zgodnie z harmonogramem. Aby tego użyć, należy utworzyć aplikację wiersza polecenia, która jest wykonywana zgodnie z wcześniej określonym harmonogramem. Zaletą tego jest to, że nie musisz się martwić, jeśli proces będzie działał jak usługa, ponieważ jeśli z jakiegoś powodu zakończy się niepowodzeniem, po prostu uruchomi się następnym razem.Jeśli chodzi o zestawianie określonych zadań, naprawdę musisz je przechowywać w trwałym magazynie binarnym. Dopóki aplikacja wiersza poleceń nie wybierze ich z pamięci i nie uruchomi. Zrobiłem to w przeszłości, używając bazy danych Cassandra jako dostawcy stanu sesji do upychania zadań w tle dla określonych użytkowników w bazie danych Cassandra, a następnie wybrania ich z linii poleceń i wykonania ich dla użytkownika.
Być może nie było to typowe rozwiązanie marshalingowe, ale zadziałało dla mnie bardzo dobrze i okazało się bardzo eleganckim rozwiązaniem, ponieważ zaplanowane zadania przetrwały wyłączenia, problemy z siecią i każda maszyna mogła wykonać zadanie, ponieważ było ono centralnie przechowywane.
Bezwstydna promocja, ale to jest mój projekt i rozwiązanie, które krótko opisałem szczegółowo, dlatego stworzyłem projekt: http://github.com/managedfusion/fluentcassandra/
źródło
Aplikacja internetowa Cron +
Jest to sprawdzony w bitwie projekt, który skaluje się poziomo wraz z farmą internetową i zapewnia korzystanie ze stosu technologii sieciowych, który już znasz.
Oto jak to działa:
http://mydomain.com/system/cron
.Brawo! Teraz masz trasę, która będzie wywoływana co 30 sekund. A jeśli przetworzenie żądania zajmie 5 minut, nikogo to nie będzie obchodzić, ponieważ nie jest ono częścią żądania strony użytkownika.
cron
Akcja kończy się patrząc bardzo prosta: ma listę metod, aby wykonać na określonej częstotliwości. Kiedy przychodzi żądanie, sprawdza, czy istnieje metoda, która musi zostać wykonana, i wywołuje odpowiednią metodę. Oznacza to, że możesz kontrolować harmonogram w swojej bazie danych , gdzie prawdopodobnie masz już wiele innych ważnych danych konfiguracyjnych dla swojej witryny.Co ważniejsze (dla ciebie), oznacza to, że twoje prace nie muszą być wywoływane według ustalonego harmonogramu. Możesz napisać dowolną logikę określającą, kiedy wykonać metodę.
Plusy i minusy
PlusyUwaga: jeśli masz jakieś pytania lub wątpliwości, dodaj komentarz . Z przyjemnością opracowuję.
źródło
Próbowałem i wykorzystałem prawie każdy możliwy sposób, aby to zrobić w mojej bieżącej aplikacji. Zacząłem robić to samo, co obecnie, odsuwając na bok prośbę użytkownika o wypełnienie danych, a następnie buforując je dalej. Uświadomiłem sobie, że to też był zły pomysł (zwłaszcza, gdy skalujesz się na wiele serwerów internetowych, więcej użytkowników przyjmuje trafienie).
Mam również zaplanowane zadanie, które trafia na adres URL w aplikacji ASP.NET - jest to przyzwoite rozwiązanie, ale zaczyna się psuć w momencie, gdy przeskakujesz przez 1 serwer WWW.
Obecnie używam dwóch różnych metod, obie wykorzystują Quartz.NET, który jest świetną małą biblioteką. Pierwszym z nich jest Quartz.NET działający w trakcie procesu z ASP.NET, jest instalowany w global.asax i działa co kilka minut. Używam tego do aktualizacji poza pasmem pamięci podręcznej ASP.NET, co jest jedynym powodem, dla którego jest uruchamiany jako część ASP.NET.
Po drugie, napisałem bibliotekę do zawijania Quartz.NET o nazwie DaemonMaster - ułatwia to upuszczenie biblioteki DLL do katalogu i uruchomienie jej w usłudze Windows. Odkryłem, że pomaga to uniknąć niektórych irytujących części pracy z usługą Windows, a także czyści niektóre aplikacje Quartz.NET. Usługi uruchamiane przez DaemonMaster mają dwa różne rodzaje, pierwsze to zadania, które muszą być uruchamiane każdej nocy lub co X minut. Pozostałe zadania działają poza kolejką w oparciu o dane przychodzące z aplikacji ASP.NET. Aplikacja ASP.NET upuszcza obiekty JSON na RabbitMQ, a usługi odpytują RabbitMQ, a następnie przetwarzają dane.
Na tej podstawie sugeruję skorzystanie z usługi Windows (i sprawdzenie DaemonMaster), aw razie potrzeby skorzystanie z kolejki, takiej jak RabbitMQ, do przekazania danych z aplikacji ASP.NET do usług - działało to najlepiej ze wszystkich tych rozwiązań . Jeśli ładujesz pamięć podręczną, to uruchomienie w ASP.NET ma sens, w przeciwnym razie nie sądzę, że tak.
źródło
Zrobiłbym to we właściwy sposób i miałbym uruchomić usługę Windows, która monitoruje „kolejkę”. Mówię „kolejka”, ponieważ programowanie w / MSMQ jest podobne do wbijania gorących wibratorów w gałki oczne.
Zakochałem się w prostocie Delayed :: Job in Rails i coś podobnego można łatwo zrobić w .NET.
Zasadniczo dodajesz dowolny rodzaj
SomethingOperation
(coś, co maPerform()
metodę). Następnie po prostu serializuj odpowiednie parametry, nadaj mu priorytet, jakieś domyślne zachowanie ponownych prób i umieść je w bazie danych.Twoja usługa będzie po prostu monitorować to i pracować z kolejkami.
źródło
Jesteśmy bardzo zadowoleni z podejścia Service Bus / Message Queue / Service. Podstawowa architektura jest taka.
Witryna wysyła wiadomość do kolejki
Usługa Windows odbiera i przetwarza wiadomość we własnym czasie
Zaletą jest to, że nie ma opóźnienia dla usługi front-end, że użytkownicy są również podłączeni. Usługa systemu Windows może zostać zamknięta i zaktualizowana bez przerywania pracy na stronie głównej. Dodatkowo jest niezwykle szybki .
Jeśli nie możesz zapisać wszystkich swoich danych w wiadomości, zawsze możesz je zapisać i odzyskać później. Sugeruję użycie mechanizmu przechowywania dokumentów, takiego jak: RavenDB lub MongoDB, w którym przechowywanie zajęć bez zmian jest bardzo proste.
Witryna wysyła wiadomość do kolejki
Usługa Windows odbiera i przetwarza wiadomość we własnym czasie
Dla uproszczenia używamy: Rhino ESB i Topshelf . Konfiguracja jest niezwykle prosta i okazało się, że wprowadzenie jej do istniejącej aplikacji zajmuje bardzo mało czasu.
źródło
Jestem ciekawy, dlaczego połączenie tych dwóch nie jest realną opcją. W tej chwili uruchamiasz zadania na widokach stron, a niektóre pechowe soki blokują się, czekając 10 sekund na wyświetlenie strony. Przynajmniej tak rozumiem twoją obecną metodę.
Jednak zadania te trwają coraz dłużej wraz ze wzrostem witryny, a Ty nie chcesz pogarszać komfortu użytkowania witryny. Nawet dla kilku (a może wielu) pechowych użytkowników przez cały dzień, więc teraz myślisz o planowaniu zadań w tle.
Nie rozumiem, dlaczego praca w tle wykonywana w regularnych odstępach czasu nie może naśladować gościa. Teraz nie jestem programistą Windows, ale w świecie Linuksa ustawiłbym zadanie cron, które będzie działało w regularnych odstępach czasu i zawierałoby 2 linie kodu.
Łączy zalety obu systemów. Odbywa się to w tle. Nie wpływa na użytkowników. Nadal używa widoku strony, aby rozpocząć pracę. Widziałem już takie podejście. Zwykle jest to środek pomiędzy prostymi starymi drogami, a bardziej złożonymi drogami schodzącymi drogą.
Aktualizacja
Myślę, że można obejść problem równoważenia obciążenia, uruchamiając programy uruchamiające zadania na samych serwerach WWW. Moduł uruchamiający zadanie wyciąga adres URL z kolejki zadań i uruchamia go w następujący sposób:
Ze względu na charakter kolejek zadań / wiadomości zadania będą równomiernie rozłożone wśród osób wykonujących zadania, co oznacza, że special_crafted_url jest ostatecznie dystrybuowany między serwerami WWW.
źródło
specially_crafted_url
pochodzi ze znanego adresu IP, możesz dodać regułę do modułu równoważenia obciążenia, aby wykonać rundę okrężną tylko dla żądań z tego adresu IP.Myślę, że wadą podejścia opartego na czystej usłudze jest to, że masz kod rozproszony w usłudze i oddalony od podstawowej aplikacji.
Oto, co zrobiliśmy z dużymi zadaniami w tle, które nie są wrażliwe na czas, co utrzymuje kod razem i upraszcza usługę:
Jeszcze prościej, wystarczy wywołać połączenie w aplikacji konsoli i użyć Harmonogramu zadań lub VisualCron, aby przekształcić je w „usługę”.
źródło
Podobał mi się TopShelf. Zachowuje prostotę, ale nadal robi to we właściwy sposób, działając jako usługa systemu Windows. Zasadniczo utwórz aplikację konsolową, dodaj około 15-20 wierszy kodu, a następnie zostanie ona zainstalowana jako usługa.
http://code.google.com/p/topshelf/
źródło
Co powiesz na posiadanie bardzo prostej usługi Windows, która działa na serwerze WWW i okresowo trafia na konserwacyjny adres URL, który wykonuje różne zadania. Niech przepustnica, ile pracy wykonuje w danym żądaniu.
źródło
Mam zamiar wykreślić widoczny trend i zasugerować wybór modelu in-IIS. Sam go użyłem i działa naprawdę dobrze. Naprawdę nie jest tak trudno wdrożyć przyzwoitą klasę puli wątków (z biegiem lat rozszerzyłem klasę puli wątków, aby wspierać dynamiczne tworzenie i niszczenie wątków, ponawianie prób itd.). Zalety to:
Moim zdaniem rozwiązanie w IIS jest po prostu „kolejnym krokiem” od nałożenia pracy na przypadkowe wyświetlenia stron.
źródło
Resque jest miła. Lub nawet Kthxbye, jeśli musisz zostać powiadomiony o wartości wynikowej po jej zakończeniu.
Zarówno na bazie Redis / Ruby.
Szczerze mówiąc, jeśli stosujesz podejście oparte na usługach, tak naprawdę nie musi ono być super zintegrowane z twoją obecną platformą, co uważam za plus. Mam nadzieję, że może to być system typu „ustaw i zapomnij”, który działałby (z pewnego rodzaju monitoringiem) i wykonywał kompletne zadania. Nie jestem pewien, czy w ogóle musi być uruchomiony na tej samej platformie, ponieważ tylko aktualizuje / modyfikuje informacje o bazie danych.
Jestem całkiem pewien, że możesz uzyskać znacznie więcej za dużo mniej, jeśli hodujesz ten rodzaj pracy dla osobnego podmiotu, zwłaszcza, że wydaje się, że masz problemy z wątkami. Zarówno Resque i Kthxbye przenieść się przetwarzanie oddzielnych procesach pozwalających na system operacyjny do obsługi współbieżności.
Resque
Kthxbye
źródło
Korzystałbym z usługi WCF hostowanej przez WAS, nasłuchując kolejki MSMQ.
Pro's
Odpal i zapominaj wiadomości jednokierunkowe z aplikacji internetowej
Ograniczanie MSMQ / WCF i ponawianie
Gwarancja dostawy; D
Zarządzanie listami martwymi
Przetwarzanie rozproszone
Aktywacja WAS / MSMQ
Cons
Funkcje MSMQ w WCF sprawiają, że korzystanie z MSMQ jest naprawdę przyjemne. Tak, będziesz krwawił z konfiguracji, ale korzyści przeważą poświęcenie.
źródło
Wpadłem na to kilka razy podczas tworzenia aplikacji internetowych. Rozwiązaliśmy go, tworząc aplikację konsoli Windows wykonującą zadanie i tworząc zaplanowane zadanie, które uruchamia się tak często, aby faktycznie wykonać zadanie.
źródło
Możesz przetaczać pracę nad wątkiem w tle (lub wieloma wątkami w tle) za pomocą Rx i czegoś takiego:
Używać:
Poprowadź to wszystko w klasie, której jest tylko jeden (inaczej singleton, ale rób to poprawnie - użyj pojemnika IoC, aby określić styl życia).
Możesz kontrolować rozmiar puli wątków itp., Pisząc niestandardowy harmonogram zamiast używania EventLoopScheduler (który uruchamia pojedynczy wątek).
źródło
Zaimplementowałem tego typu rzeczy kilka razy. W systemie Windows skonfigurowałem program wiersza polecenia Pythona, który robi coś w różnych momentach. Ten program udostępnia także interfejs xmlrpc na porcie. Następnie zadanie zaplanowanego zadania jest uruchamiane co minutę i odpytuje interfejsy xmlrpc. Jeśli nie są uruchomione, próbuje je uruchomić. Jeśli nie, wysyła mi e-maile.
Zaletą jest to, że uruchamiane zadanie nie jest powiązane z cronem ani harmonogramem. Mam zadanie procesowe, które uruchamia się co sekundę, ale będzie czekać dłużej i dłużej między rozpoczęciem nowego zadania, w zależności od tego, czy miało ono zadanie do wykonania. Można go również wykorzystać do inteligentnego działania w oparciu o wynik. Masz błąd 500? Masz naprawdę duże opóźnienie? Zrób coś innego. Powiadom inną usługę. Itp.
Ten sam system działa na Uniksie, z niewielkimi modyfikacjami.
źródło
Sam nie mam dla ciebie odpowiedzi, ale problem zadzwonił - pamiętam przypadkowych facetów, którzy dyskutowali o tym na podcastie .
źródło
Omówienie interfejsu API Java kolejki zadań
Pojęcia dotyczące zadania
W przetwarzaniu w tle App Engine zadanie jest pełnym opisem małej jednostki pracy. Ten opis składa się z dwóch części:
Zadania jako haki internetowe offline
Na szczęście Internet już zapewnia takie rozwiązanie, w postaci żądania HTTP i jego odpowiedzi. Ładunek danych to treść żądania HTTP, na przykład zmienne formularza internetowego, XML, JSON lub zakodowane dane binarne. Odwołaniem do kodu jest sam adres URL; rzeczywisty kod jest logiką wykonaną przez serwer podczas przygotowywania odpowiedzi.
źródło
Zrób jedno i drugie
Dodaj opcjonalny parametr do ścieżki pytania, który wykonuje pracę, w której obecnie pracujesz na żądanie użytkownika:
Obsługa zadań w tle w dużej witrynie
Utwórz aplikację konsoli, która działa na każdym serwerze i otwiera współdzielony plik binarny dziennika IIS i odczytuje go do bieżącego końca pliku. Za pomocą obserwatora systemu plików lub interwału czasowego czytaj dalej, aby zbierać aktualizacje, gdy IIS opróżnia dziennik.
Skorzystaj z tych informacji, aby ustalić, które strony były aktualnie przeglądane.
Użyj adresów URL strony z przeanalizowanego dziennika, aby wywołać wersję „extrastuff” adresu URL na localhost z obiektem webclient.
Dodaj kod, aby przełączyć pliki na koniec każdego okresu rejestrowania lub ponownie uruchom proces po każdym okresie rejestrowania.
źródło