2012-01-15 10 views
12

Czy ktoś może mi doradzić, w jaki sposób ekwipunek nie sprawdza się, gdy wystąpią wyjątki lub kiedy wystąpią błędy?Warunki błędu i ponowienia w gearmanie?

Używam klienta python gearman w aplikacji Django, a moi pracownicy są inicjowani jako polecenie Django. Przeczytałem z tego blog post, który ponawia próbę z powodu błędów nie są proste i wymaga on sys.exit od strony pracownika.

Czy zostało to poprawione, aby spróbować ponownie przy użyciu sendFail lub sendException? Potwierdza to również wsparcie dla gearmanów z algorytmem wykładniczym - powiedzmy, że jeśli wystąpi błąd , ponowna próba SMTP nastąpi po 2,4,8,16 sekundach itd.?

+0

sys.exit() jest złym pomysłem dla Gearmana - zazwyczaj będzie ponawiał każdą taką pracę na zawsze (chyba że masz ustawione Retrole zadań podczas uruchamiania demona). Po prostu wykonaj 'return stringvar' z dowolnym statusem/wynikami z zadania (np. Klucz do wiersza DB lub pamięci podręcznej z prawdziwymi informacjami). – RichVel

Odpowiedz

25

Moim zdaniem Gearman stosuje podejście "to nie moja sprawa" - np. Nie ingeruje w wykonywane zadania, chyba że pracownicy się zawiesią. Wszelkie komunikaty o sukcesie/niepowodzeniach powinny być obsługiwane przez klienta, a nie sam serwer Gearman.

W planie pracy, oznacza to, że wszystko sendFail()/sendException() i inne send*() są skierowane do klienta i to do klienta, aby zdecydować, czy ponowić ofertę lub nie. Ma to sens, ponieważ czasami nie trzeba się ponownie próbować.

W pracy w tle wszystkie funkcje send*() tracą znaczenie, ponieważ nie ma klienta, który będzie słuchał wywołań zwrotnych. W rezultacie wysłane wiadomości zostaną po prostu zignorowane przez Gearmana. Jedyny warunek, w którym zadanie zostanie ponowione, to sytuacja, w której pracownik ulega awarii (co można naśladować komendą exit(XX), gdzie XX ma wartość niezerową). To oczywiście nie jest coś, co chcesz robić, ponieważ pracownicy zazwyczaj mają być długotrwałymi procesami, a nie tymi, które muszą być ponownie uruchomione po każdej nieudanej pracy.

Osobiście rozwiązałem ten problem poprzez rozszerzenie domyślnej klasy GearmanJob, w której przechwytywam wywołania funkcji send*(), a następnie wdrażam mechanizm ponawiania. Zasadniczo przekazuję wszystkie dane związane z ponownym przetwarzaniem (maksymalna liczba ponownych prób, czasy, które zostały już ponownie sprawdzone) wraz z obciążeniem, a następnie przetwarzam wszystko samodzielnie. Jest to trochę kłopotliwe, ale rozumiem, dlaczego Gearman działa w ten sposób - po prostu pozwala obsłużyć całą logikę aplikacji.

Wreszcie, jeśli chodzi o możliwość ponawiania zadań z wykładniczym limitem czasu (lub z jakimkolwiek przekroczeniem limitu czasu). Gearman ma funkcję dodawania opóźnionych zadań (poszukaj SUBMIT_JOB_EPOCH w protocol documentation), ale nie jestem pewien co do jej statusu - rozszerzenia PHP i, jak sądzę, moduł Pythona go nie obsługuje, a doktorzy mówią, że można go usunąć w przyszłość. Ale rozumiem, że działa to w tej chwili - wystarczy, że przekażesz Gearmanowi żądania surowych gniazdek, aby to się stało (a część wykładnicza powinna zostać zaimplementowana również po twojej stronie).

Jednak this blog post twierdzi, że implementacja SUBMIT_JOB_EPOCH nie jest skalowalna. Korzysta z node.js i setTimeout(), aby działało, widziałem, jak inni używają narzędzia unixowego at, aby zrobić to samo. W jakikolwiek sposób - Gearman nie zrobi tego za ciebie. Skoncentruje się na niezawodności, ale pozwoli ci skupić się na całej logice.

+5

Wiem, że to odpowiedź na stare pytanie, ale widziałem wiele osób borykających się z ten sam problem i uważam, że warto raz na zawsze zapewnić pełny obraz. – Aurimas