Jak zaprojektować oprogramowanie, które aktualizuje kilka mikrousług, jeśli jedna z nich zawiedzie?

12

Czy istnieje wzór lub praktyka projektowa, z której można skorzystać, aby pomóc z usługami, które nie działają lub przestają działać, a inne są stabilne?

Co jeśli mam trzy mikrousługi, a dwie z nich są dobre, a jedna umiera w środku testu POST? Dwa dostaną POST, a jeden nie. Nie sądzę, że mogę przeprowadzać transakcje, ponieważ wysyłam moje żądania do usługi.

Jak mogę to zaprojektować? Nie chcę osieroconych danych w różnych bazach danych.

Jasio
źródło
6
Nie jest to prosty problem do rozwiązania. Widziałem, jak zostało to wdrożone jako kolejka do usług (ostateczna spójność), ponieważ najprawdopodobniej nie masz kontroli nad usługami, a narzucanie menedżerów transakcji lub możliwości transakcyjnych jest w najlepszym razie bzdurą i prawdopodobnie nie jest dobrym pomysłem w środowisku SOA. Widziałem to głównie wokół mobilnego pchania, gdzie możesz mieć połączenie z miejscem docelowym.
Mike
kwas nad mikrousługami to trudny orzech do zgryzienia, inną opcją może być szyna, używając redis publikuj / subskrybuj lub projektuj kolejki i wysyłaj raz z kanału przychodzącego, a następnie Twoje usługi subskrypcji lub serwery proxy docierają do celów i zgłaszają sukces niepowodzenie. Będziesz musiał monitorować awarie i mieć do tego przepływ. Możesz również mieć awarie, w których transakcja nie jest ważna w jednej usłudze, ale ważna w dwóch innych, ale to tylko kolejny błąd, który musisz rozwiązać.
Tim Cederquist,
Czy nie użyłby czegoś takiego jak „menedżer kolejek”, co wydaje mi się, że Redis spowodowałby wąskie gardło? A przynajmniej ma duży potencjał? Nie znam też innego sposobu niż ty opisałeś.
Johnny
W zależności od natężenia przepływu danych wdrożyłem menedżera kolejek, który ponawia próby transmisji do momentu zgłoszenia sukcesu lub wysyła nieudane powiadomienie i wysyła powiadomienie SMS o awarii. Wydaje mi się, że będzie to trochę zależeć od oczekiwanego okresu wyłączenia (jak długo).
htm11h
Czy po to jest coś takiego jak rabbitmq?
Johnny

Odpowiedzi:

9

Niektóre opcje.

Użyj stałego kanału komunikacji

Zamiast HTTP upuszczaj wiadomości w kolejce, która jest wysoce dostępna i trwała. Np. Kafka. Tak długo, jak serwer docelowy stanie się dostępny w pewnym momencie, otrzyma komunikat.

Masz kompromis polegający teraz na udostępnianiu i administrowaniu złożonym podsystemem (kolejką). Upewnij się więc, czy przeanalizujesz, czy jest to opłacalne.

Wycofaj i spróbuj ponownie

Niech osoba dzwoniąca zachowa nieudane żądanie (być może utrwalone na dysku) i okresowo ponowi próbę. W tym przypadku ważne jest rozróżnienie między żądaniem powodującym awarię a usługą, która właśnie nie działa. Ten pierwszy jest prawdopodobnie spowodowany błędem i powinien być zalogowany ... ponowna próba prawdopodobnie nie zrobi różnicy, dopóki nie zostanie wykonana poprawka.

Wykryj i zrekompensuj

Okresowe zadanie sprawdza warunki spójności między mikrousługami. Np. Dzienniki awarii aż do bezpośrednich zapytań API w razie potrzeby. Jeśli wykryje problem (np. Istnieje zamówienie, ale lista wysyłkowa nigdy nie otrzymała przesyłki), wykonaj kroki kompensacyjne. Tymi krokami mogą być utworzenie zgłoszenia do pomocy technicznej lub wysłanie wiadomości e-mail do kogoś innego.

Rozważ alternatywy projektowe

Taki przypadek prawdopodobnie wymaga bramy API do zarządzania połączeniami do dotkniętych mikrousług. W ten sposób kontrolujesz, które taktyki są stosowane w celu złagodzenia tego problemu. Prawdopodobnie nie chcesz obciążać klientów tymi szczegółami implementacji. Zobacz wzór wyłącznika .

Ponieważ mikrousług są niezależne, zawsze istnieje pewien przypadek awarii, który może powodować niespójność. Musisz być przygotowany na ręczne poprawki, gdy się pojawią.

Jeśli potrzebujesz silnej konsystencji, mikrousługi nie będą dobrze dopasowane. Jeśli nadal potrzebujesz skalowalności, możesz rozważyć dzielenie na fragmenty, w którym powiązane dane mogą być kolokowane na tym samym fragmencie, aby zagwarantować spójność. Nadal możesz skalować IO, dodając odłamki.

Jeśli potrzebujesz silnej spójności i nie masz problemów ze skalowalnością, skorzystaj z usług monolitycznych. Użyj bibliotek jako granic w aplikacji, aby rozdzielić obawy.

Kasey Speakman
źródło
Czy po to jest RabbitMQ?
Johnny
Czy RabbitMQ jest odpowiedzią na twoje pytanie? Nie. Może to być część rozwiązania, które spełnia Twoje potrzeby, ale nie rozwiąże problemu samodzielnie.
Kasey Speakman,
Tylko uwaga. Myślę, że RabbitMQ nie utrzymuje wiadomości. Jest zużyty i usunięty z kolejki, więc NIE. Jeśli potrzebujesz wytrwałości i spróbuj ponownie, RabbitMQ nie pomoże.
Laiv
2

Myślę, że opisujesz problem konsensusu: nie chcesz zatwierdzać, chyba że każdy uczestnik rozproszonej transakcji stwierdzi, że operacja się powiodła. Prostym rozwiązaniem tego jest dwufazowe zatwierdzenie. Zasadniczo etapuje transakcję w każdym systemie, dopóki każdy nie poinformuje, że etapowanie się powiodło (faza 1). Jeśli każdy uczestnik transakcji zwróci sukces, każdemu poleca się dokonać; jeśli którykolwiek z nich zwrócił awarię, następuje wycofanie (Faza 2). Jest to pomarszczone, co prowadzi do bardziej złożonego rozwiązania Three Phase Commit. Możesz przeczytać o wiele lepszy opis każdego z nich tutaj:

http://the-paper-trail.org/blog/consensus-protocols-two-phase-commit/

http://the-paper-trail.org/blog/consensus-protocols-three-phase-commit/

iarejenius
źródło