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.
Odpowiedzi:
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.
źródło
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/
źródło