Istnieje wiele rozwiązań, które kompromisują bardziej, niż czuję się swobodnie. To prawda, że jeśli twoja sprawa użycia jest złożona, na przykład przenoszenie pieniędzy między różnymi bankami, przyjemniejsze alternatywy mogą być niemożliwe. Ale spójrzmy na to, co możemy zrobić we wspólnym scenariuszu, w którym użycie mikrousług zakłóca nasze przyszłe transakcje w bazie danych.
Opcja 1: Jeśli to możliwe, unikaj potrzeby transakcji
Oczywiste i wspomniane wcześniej, ale idealne, jeśli damy radę. Czy komponenty faktycznie należały do tej samej mikrousługi? Czy możemy przeprojektować system (systemy) tak, aby transakcja stała się niepotrzebna? Być może akceptacja braku transakcji jest najbardziej przystępną ofiarą.
Opcja 2: Użyj kolejki
Jeśli istnieje wystarczająca pewność, że druga usługa odniesie sukces we wszystkim, co chcemy, możemy wywołać ją za pomocą jakiejś formy kolejki. Element w kolejce nie zostanie odebrany do później, ale możemy upewnić się, że element jest w kolejce .
Powiedzmy na przykład, że chcemy wstawić podmiot i wysłać wiadomość e-mail jako pojedynczą transakcję. Zamiast dzwonić na serwer pocztowy, umieszczamy wiadomość w kolejce w tabeli.
Begin transaction
Insert entity
Insert e-mail
Commit transaction
Oczywistą wadą jest to, że wiele mikrousług będzie potrzebowało dostępu do tej samej tabeli.
Opcja 3: Wykonaj zewnętrzną pracę, tuż przed sfinalizowaniem transakcji
Podejście to opiera się na założeniu, że popełnienie transakcji jest bardzo mało prawdopodobne.
Begin transaction
Insert entity
Insert another entity
Make external call
Commit transaction
Jeśli zapytania nie powiodą się, połączenie zewnętrzne jeszcze się nie odbyło. Jeśli połączenie zewnętrzne nie powiedzie się, transakcja nigdy nie zostanie zatwierdzona.
Takie podejście wiąże się z ograniczeniami polegającymi na tym, że możemy wykonać tylko jedno połączenie zewnętrzne i musi być wykonane na końcu (tzn. Nie możemy wykorzystać jego wyniku w naszych zapytaniach).
Opcja 4: Twórz rzeczy w stanie oczekiwania
Jak opublikowano tutaj , możemy mieć wiele mikrousług tworzących różne komponenty, każdy w stanie oczekiwania, bez transakcji.
Sprawdzanie poprawności jest wykonywane, ale nic nie jest tworzone w stanie ostatecznym. Po pomyślnym utworzeniu wszystkiego każdy komponent jest aktywowany. Zwykle ta operacja jest tak prosta, a prawdopodobieństwo, że coś pójdzie nie tak, jest tak małe, że możemy nawet zdecydować się na aktywację bez transakcji.
Największą wadą jest prawdopodobnie to, że musimy uwzględnić istnienie oczekujących przedmiotów. Każde wybrane zapytanie musi rozważyć, czy dołączyć oczekujące dane. Większość powinna to zignorować. A aktualizacje to zupełnie inna historia.
Opcja 5: Pozwól mikroserwisowi udostępnić swoje zapytanie
Żadna z pozostałych opcji tego nie robi dla Ciebie? Zatem bądźmy niekonwencjonalni .
W zależności od firmy ta może być nie do przyjęcia. Jestem świadomy. To jest niekonwencjonalne. Jeśli to nie do przyjęcia, wybierz inną trasę. Ale jeśli pasuje to do Twojej sytuacji, rozwiązuje problem prosto i skutecznie. To może być najbardziej akceptowalny kompromis.
Istnieje sposób na przekształcenie zapytań z wielu mikrousług w prostą, pojedynczą transakcję bazy danych.
Zwraca zapytanie zamiast go wykonywać.
Begin transaction
Execute our own query
Make external call, receiving a query
Execute received query
Commit transaction
Jeśli chodzi o sieć, każda mikrousługa musi mieć dostęp do każdej bazy danych. Należy o tym pamiętać, również w odniesieniu do skalowania w przyszłości.
Jeśli bazy danych biorące udział w transakcji znajdują się na tym samym serwerze, będzie to zwykła transakcja. Jeśli są na różnych serwerach, będzie to transakcja rozproszona. Kod jest taki sam, niezależnie od tego.
Otrzymujemy zapytanie, w tym jego typ połączenia, parametry i ciąg połączenia. Możemy zawinąć je w czystą, wykonalną klasę Command, dzięki czemu przepływ będzie czytelny: Wywołanie mikrousług powoduje powstanie polecenia, które wykonujemy w ramach naszej transakcji.
Ciąg połączenia jest tym, co daje nam inicjująca mikrousługa, więc dla wszystkich celów i celów kwerenda jest nadal uważana za wykonaną przez tę mikrousługę. Po prostu fizycznie kierujemy go przez mikrousługę klienta. Czy to robi różnicę? Pozwala nam to umieścić tę samą transakcję z innym zapytaniem.
Jeśli kompromis jest akceptowalny, to podejście daje nam prostą transakcyjność aplikacji monolitowej w architekturze mikrousługowej.