Obsługa zadań w tle w dużej witrynie

49

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.

Czy brakuje mi innych zastrzeżeń do procesu łączenia pul wątków / kolejek roboczych procesu IIS?

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?

Kevin Montrose
źródło
Właściwy sposób to sposób, w jaki decydujesz się pójść w drugą stronę, i spoglądasz wstecz, mówiąc, że powinniśmy to zrobić we właściwy sposób. Wybierz mądrze. Nie znam się jednak na świecie IIS, aby skomentować ten konkretny problem.
Chris,
2
Jestem ciekawy, ponieważ mam podobny scenariusz (na znacznie mniejszą skalę) i ja też jestem po prostu wsparciem dla losowych użytkowników, którzy mają pecha. Nie znam najlepszego rozwiązania, więc podążę tutaj. :-)
pc1oad1etter 22.10.10
7
Nie rozumiem, dlaczego nie ma tego w StackOverflow. Jest to kompromis inżynieryjny, a nie subiektywna wycena. Pytasz o analizę różnych podejść - to wszystko jest obiektywne. Dopiero gdy analiza wyjaśni, jakie dokładnie są kompromisy, jest w tym jakaś subiektywność i, o ile widzę, twoje pytanie nie brzmi „co powinienem uważać za ważniejsze, mój czas i zasoby serwera lub czas mojego użytkownika? „ lub coś podobnego.
Joren
@Kevin Montrose - z twoich komentarzy wydaje się, że rozróżniasz między „trzeba to zrobić wkrótce” i „zaplanowanym w odstępach czasu”. Czy możesz wyjaśnić, dlaczego są to dwa różne rodzaje zadań w tle, które wymagają innego wzorca / infrastruktury?
Portman
@Portman - Zasadnicza różnica polega na tym, że zadań „wkrótce” nie można wykonać spekulacyjnie, naprawdę musimy poczekać, aż się zorientujemy, że trzeba je wykonać. Niektóre obliczenia z tyłu koperty pokazują, że gdybyśmy przenieśli zapytania „Powiązane pytania” (tylko jedno z wielu) do „głupiej” karty cron, zajęłoby to około. tydzień solidnej egzekucji, aby przejść przez wszystkie pytania. Zasadniczo chcielibyśmy, aby były one uruchamiane tak szybko, jak to możliwe (bez wpływu na wrażenia użytkownika), podczas gdy nasze zadania interwałowe można uzyskać, uruchamiając je nie częściej niż raz na 5 minut (i zwykle znacznie rzadziej).
Kevin Montrose

Odpowiedzi:

17

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):

  1. Możesz opracować internetowy interfejs użytkownika za pośrednictwem swojej usługi (ponieważ działa jako aplikacja internetowa). Jest to niezwykle przydatne, aby zobaczyć, co dzieje się w czasie wykonywania.
  2. Model wdrażania aplikacji internetowych będzie działał dla aplikacji usługowej.
  3. Usługi IIS zapewniają kilka ciekawych funkcji do obsługi awarii aplikacji (pod pewnymi względami podobne do usługi Windows).
  4. Programiści bardzo dobrze znają się na tworzeniu aplikacji internetowych (oczywiście), większość z nich nie wie zbyt wiele o najlepszych praktykach podczas opracowywania usługi Windows.
  5. Zapewnia szereg alternatyw dla ujawnienia interfejsu API, z którego mogą korzystać inne aplikacje.

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:

  1. Bezpieczeństwo . Może istnieć inny model zabezpieczeń dla interfejsu użytkownika wyświetlający informacje o uruchomionych procesach w tle. Nie chciałbym udostępniać tego interfejsu użytkownika nikomu oprócz zespołu operacyjnego. Ponadto aplikacja internetowa może działać jako inny użytkownik z podwyższonym zestawem uprawnień.
  2. Konserwacja . Byłoby wspaniale móc wdrożyć zmiany w aplikacji obsługującej procesy działające w tle bez wpływu na korzystanie z witryny przez użytkownika.
  3. Wydajność . Oddzielenie aplikacji od żądań użytkowników przetwarzających główną witrynę oznacza, że ​​wątki w tle nie zmniejszą zdolności IIS do obsługi kolejki żądań przychodzących. Ponadto w razie potrzeby aplikacja przetwarzająca zadania w tle może zostać wdrożona na osobnym serwerze.

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.

Rohland
źródło
Podstawowy pomysł korzystania z oddzielnej strony internetowej jako usługi jest intrygujący, o której nie pomyślałem ...
Kevin Montrose
Rohland, może coś tu brakuje, ale wydaje się, że mówisz, że wchodziłeś w interakcję z usługą systemu Windows z poziomu programu obsługi NServiceBus, a następnie usługa wysyła wiadomość e-mail. Jeśli mam rację, czy mogę zapytać, dlaczego po prostu nie wysyłasz wiadomości e-mail z programu obsługi wiadomości NServiceBus, który bardzo łatwo byłoby opracować, przetestować i wdrożyć?
Sean Kearon
Witryna wysyła komunikat do usługi Windows. Program obsługi wiadomości NServiceBus usługi Windows odbiera wiadomość i wysyła wiadomość. Zasadniczo jest to ten sam proces, który opisujesz.
Rohland
22

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 CRONzadanie polegające na uruchomieniu części infrastruktury. W systemie Windows jest to znane jako task schedulerbardzo 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/

Nick Berardi
źródło
2
Robię to z moją wspólną usługą hostingową, ponieważ nie mam dostępu do powłoki. Napisz stronę PHP, która robi coś ważnego, a następnie zlecaj cronowi okresowe ładowanie strony przy użyciu wget lub rysia. To brzmi jak rodzaj rzeczy, która działałaby w tym przypadku i byłaby niezwykle prosta, prawie nie wymagająca zmiany sposobu, w jaki rzeczy są obecnie wykonywane.
Ricket
Co za proste rozwiązanie. Zaowocowało pomysłami na mój własny projekt, których nawet nie rozważałem. Ponadto masz pełny dostęp do istniejącej bazy kodu. Wystarczy dodać projekt konsoli do rozwiązania i odwołać się do istniejących projektów.
Tim Murphy
10

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:

  1. Utwórz kontroler / akcję w swojej aplikacji internetowej, aby obsłużyć zaplanowane zadania w tle. Z reguły zazwyczaj nazywam mój http://mydomain.com/system/cron.
  2. Ze względów bezpieczeństwa tę akcję należy zablokować tylko dla uwierzytelnionych adresów IP w sieci lokalnej.
  3. Na osobnej maszynie zainstaluj Wget i skonfiguruj Zaplanowane Zadanie, aby Wget pobierał zasób z kroku 1. Możesz sprawić, aby zadanie było uruchamiane tak często, jak chcesz (zazwyczaj wybieram na 30 sekund). Nie zapomnij przekazać odpowiedniego argumentu dotyczącego plików cookie do Wget, aby uwierzytelniał się w Twojej aplikacji internetowej.
  4. Aby uzyskać nadmiarowość, możesz również zainstalować drugi zaplanowany wget na drugim komputerze.

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.

cronAkcja 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

Plusy
  • Jesteś już bardzo dobry w pisaniu kodu ASP.NET MVC, dzięki czemu możesz pisać zadania w tle na tej samej platformie , na której piszesz resztę rozwiązania.
  • Zadania działają w tym samym kontekście co twoja aplikacja internetowa, dzięki czemu możesz współdzielić pamięć podręczną i skorzystać z metod pomocniczych, które już istnieją.
  • Jeśli wget pobiera identyfikator URI z równoważeniem obciążenia , zadania w tle są teraz również równoważone z obciążeniem.
  • Jednoczesne wdrażanie - nie musisz się martwić synchronizacją aplikacji internetowej z logiką zadań w tle, ponieważ wszystkie są w tym samym wdrożeniu.
Cons
  • Przez lata kilka osób powiedziało mi, że ten projekt jest „bardzo sprzężony”, ale po naciśnięciu nie byli w stanie wyrazić, dlaczego jest to zła rzecz.

Uwaga: jeśli masz jakieś pytania lub wątpliwości, dodaj komentarz . Z przyjemnością opracowuję.

Portman
źródło
7

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.

James Avery
źródło
6

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 ma Perform()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.

Ben Scheirman
źródło
Serializacja odpowiednich parametrów nie jest tak naprawdę „sprawiedliwa”, jest prawie „wszystkim”. To jedna z moich większych wątpliwości co do osobnego podejścia procesowego ...
Kevin Montrose
Tak, to jest to samo rozwiązanie, którego użyłem, jednak serializowałem cały obiekt do bazy danych jako plik binarny, a następnie wyciągnąłem go, aby wykonać. Użyłem Cassandry jako mojego trwałego magazynu, a Harmonogram zadań jako mojego harmonogramu CRON dla aplikacji wiersza poleceń, która uruchamiałaby i wykonywała zadania.
Nick Berardi
Zaczęliśmy od umieszczenia w wiadomości zwykłego fragmentu danych i wyrzucenia całego obiektu. Nadal działało świetnie. Rozważałbym tę separację, ponieważ ma ona również inne zalety.
Nathan Palmer,
@Kevin - gdybyśmy mieli kilku ludzi z dużą historią serializacji ...
Marc Gravell
4

Jesteśmy bardzo zadowoleni z podejścia Service Bus / Message Queue / Service. Podstawowa architektura jest taka.

Witryna wysyła wiadomość do kolejki

bus.Send(new ProjectApproved()); // returns immediately

Usługa Windows odbiera i przetwarza wiadomość we własnym czasie

public class DoesSomethingAwesome : ConsumerOf<ProjectApproved>
{
   public void Consume(ProjectApproved Message)
   {
      // Do something "offline"
   }
}

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

// Save your object
store.Save(completeProject);

// Send a message indicating its ready to be processed
bus.Send(new ProjectApproved() { ProjectId = completeProject.Id });

Usługa Windows odbiera i przetwarza wiadomość we własnym czasie

public class DoesSomethingAwesome : ConsumerOf<ProjectApproved>
{
   public void Consume(ProjectApproved Message)
   {
      // Retrieve your object back
      var completeProject = store.Get(Message.ProjectId);
   }
}

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.

Nathan Palmer
źródło
W każdym razie użycie magistrali usług z CQRS jest zawsze dobrym sposobem na zwiększenie skalowalności
pomyśl kodowanie
3

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.

#!/bin/bash
wget -O /dev/null http://stackoverflow.com/specially_crafted_url

Łą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:

wget -O /dev/null http://localhost/specially_crafted_url

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.

łagodny
źródło
Robimy to już dla wszystkiego, co działa w przewidywalnych odstępach czasu, pozostały nam rzeczy, których nie można przewidzieć zbyt daleko. Na przykład „blok pytań powiązanych” jest aktualizowany tylko w przypadku pytań, które były ostatnio przeglądane. Listy otagowanych pytań są również buforowane tylko wtedy, gdy ktoś chce sprawdzić te tagi. Ponieważ mamy ponad milion pytań i zbliżamy się do 25 tys. Tagów, nie możemy uruchomić wszystkich powiązanych zadań (a to tylko 2 przykłady) „na wszelki wypadek”.
Kevin Montrose
Istnieją również problemy z równoważeniem obciążenia, ponieważ SO jest podzielone na wiele serwerów. Zasadniczo, jeśli masz stronę stackoverflow.com, zawsze trafisz na ten sam serwer. Metoda wget zmusiłaby nas do przeniesienia wszystkich zadań na jeden serwer (lub naprawdę przerobienia konfiguracji równoważenia obciążenia), co byłoby bardzo bolesne.
Kevin Montrose
Fajnie, jeśli wszystko działało w regularnych odstępach czasu, co? Rozumiem, co mówisz, ale metodologia opisana powyżej (i myślę, że wspomniana przez kilka innych osób) się nie zmienia. Gdy wyświetlenia strony mówią „czas uruchomić to zadanie”, umieszczasz je w kolejce wiadomości. Długotrwałe zadanie w tle uruchamia znalezione zadania. W tym przypadku zadania to nic więcej niż adresy URL, o które należy poprosić. hehe Prawdopodobnie możesz to skonfigurować na współdzielonym serwerze za 20 USD, ponieważ nie wymaga on uruchamiania kodu. Spójrz na Amazon SQS, aby uzyskać łatwą w obsłudze usługę przesyłania wiadomości.
mellowsoon
Odnośnie problemów z równoważeniem obciążenia. Tam, gdzie jest wola, jest sposób! Zamiast wysyłać żądanie do stackoverflow.com, możesz trafić serwer losowo, używając jego adresu IP. Jeśli moduł równoważenia obciążenia sprawdza pliki cookie w żądaniach potoku, możesz sfałszować pliki cookie. Jeśli sprawdzi adres IP, prawdopodobnie mógłbyś go nawet sfałszować (ponieważ nie obchodzi Cię odpowiedź serwera).
mellowsoon
Uzgodniono, że równoważenie obciążenia nie powinno być powodem, aby tego nie robić. Ponieważ żądanie specially_crafted_urlpochodzi 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.
Portman
2

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ę:

  1. Utwórz kolejkę zadań (w pamięci lub w DB, bez względu na to, jaka trwałość jest wymagana dla typów zadań)
  2. Utwórz usługę internetową, która będzie wykonywać zadania w kolejce
  3. Martwa, prosta usługa, która wywołuje usługę internetową w określonym przedziale czasowym, pozostawia wszystkie skomplikowane rzeczy (pobieranie i wykonywanie zadań) do usługi internetowej w podstawowej bazie kodu.

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ę”.

Brandon
źródło
1
Mam to dokładnie w znaczącej aplikacji w pracy - usłudze Windows, która co pewien czas uruchamia aplikację internetową. Aplikacja internetowa pozostaje bezstanowa i w razie potrzeby pobiera stan z bazy danych. Działa uczta.
Bevan
1

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/

Shane
źródło
1

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.

Rob Sobers
źródło
1

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:

  • Brak usług zewnętrznych do monitorowania
  • Prostota wdrożenia: bez zestawiania między procesami, bez zaawansowanego monitorowania zadań
  • Nadal jesteś w procesie IIS, więc możesz wykonywać wszystkie zwykłe rejestracje i tak dalej (nie potrzeba wielu plików dziennika)
  • Znacznie uproszczone wdrożenie (podczas aktualizacji usługi musisz ją zatrzymać, skopiować pliki, uruchomić usługę - jest to dodatek do zwykłych aktualizacji kodu witryny)

Moim zdaniem rozwiązanie w IIS jest po prostu „kolejnym krokiem” od nałożenia pracy na przypadkowe wyświetlenia stron.

Dean Harding
źródło
1

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

Lukas
źródło
Muszę spróbować Kthxbye choćby ze względu na świetne imię!
Nathan Palmer,
prawie niesamowite. następny będzie ORLY? biblioteka. prawdopodobnie do pewnego rodzaju monitorowania statystyk ...;)
Lukas
0

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

  • MSMQ (nie jest martwy ... jeszcze)

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
0

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.

John Christensen
źródło
0

Możesz przetaczać pracę nad wątkiem w tle (lub wieloma wątkami w tle) za pomocą Rx i czegoś takiego:

var scheduler = new EventLoopScheduler( SchedulerThreadName );
_workToDo = new Subject<Action>();
var queueSubscription = _workToDo.ObserveOn( scheduler ).Subscribe( work => work() );
_cleanup = new CompositeDisposable( queueSubscription, scheduler );

Używać:

var work = () => { ... };
_workToDo.OnNext( work ); // Can also put on error / on complete in here

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).

Neal
źródło
0

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.

Christopher Mahan
źródło
0

Sam nie mam dla ciebie odpowiedzi, ale problem zadzwonił - pamiętam przypadkowych facetów, którzy dyskutowali o tym na podcastie .

Spolsky: Zauważyłem, że jednym z pytań, które zadałeś na blogu, było to, jak ogólnie radzić sobie z powtarzającymi się zadaniami konserwacyjnymi?

Atwood: Tak.

Spolsky: Czy to uczciwa charakterystyka? Każda witryna ma pewne zadania, których nie chcesz wykonywać podczas ładowania strony, ale chcesz wykonać z pewnym powtarzaniem.

Atwood: Tak, zadania w tle są czymś podobnym.

Spolsky: Tak, więc co wymyśliłeś?

Atwood: Cóż, pierwotnie zapytałem na Twitterze, ponieważ chciałem tylko czegoś lekkiego. Naprawdę nie chciałem pisać usługi Windows. Czułem, że to jest poza kodem zespołu. Plus kod, który faktycznie działa, jest w rzeczywistości stroną internetową, ponieważ dla mnie jest to logiczna jednostka pracy na stronie internetowej. Tak więc to naprawdę tak, jakbyśmy oddzwonili na stronę internetową, to jest jak kolejna prośba na stronie, więc widziałem to jako coś, co powinno pozostać w zgodzie, i małe podejście, które wymyśliliśmy, które zostało mi polecone na Twitterze było zasadniczo dodać coś do pamięci podręcznej aplikacji z ustalonym terminem wygaśnięcia, wtedy masz oddzwonienie, więc kiedy to wygaśnie, wywołuje pewną funkcję, która działa, a następnie dodajesz to z powrotem do pamięci podręcznej z tym samym terminem wygaśnięcia.

Dziwne
źródło
1
Tak, to działa dla witryn znacznie mniejszych niż StackOverflow. Skala jest tutaj niestety dużym problemem (lub na szczęście, w zależności od tego, jak na nią patrzysz).
Kevin Montrose
@Kevin Montrose, tutaj twierdzę, że jestem całkowicie nieświadomy domeny. Czy mógłbyś wyjaśnić, dlaczego posiadanie tajnej strony (stron internetowych) wykonuje tę pracę (być może w małych jednostkach) i jest wywoływane przez odświeżające zadanie strony / crona, gdzie indziej nie jest skalowalne? Nie wątpię, że masz rację, ale chciałbym się uczyć.
Dziwne,
Twoja konkretna sugestia (wygasanie pamięci podręcznej) nie jest skalowana, ponieważ wszystkie wygasania pamięci podręcznej (w ASP.NET) uruchamiają jeden wątek (jest to sprytny hack dla mniejszych witryn, takich jak SO). Zadanie cron nie skaluje się, ponieważ przerośliśmy jeden serwer (SO wynosi teraz 3 i wciąż rośnie), a każde zadanie cron uderzyłoby w jeden serwer (przynajmniej zmiana tego niezmiennika byłaby naprawdę bolesna z naszym obciążeniem- konfiguracja wagi). Zadanie cron musiałoby również uruchamiać się bardzo często, ponieważ zadania te powtarzają się co kilka minut.
Kevin Montrose
Warto zauważyć, że stosujemy harmonogramowanie w stylu „cron” do rzadziej uruchamianych, ustalonych interwałów, już zadań, takich jak przyznawanie odznak i codzienne powiadomienia e-mail.
Kevin Montrose
0

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:

  • Ładunek danych, który parametryzuje zadanie.
  • Kod realizujący zadanie.

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.

antony.trupe
źródło
Nie sugeruję używania interfejsu API kolejki zadań GAE, ale podążam za ich modelem. Zastanawiali się przez chwilę i napisali implementację.
antony.trupe
0

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.

Rachunek
źródło