W luźno sprzężonej architekturze mikrousług, jak śledzisz swoje zależności?

9

Popularnym wyborem architektury wysokiego poziomu we współczesnym programie jest system mikrousług oparty na REST. Ma to kilka zalet, takich jak luźne połączenie, łatwe ponowne użycie, ograniczone ograniczenie technologii, które można zastosować, wysoka skalowalność itp.

Ale jednym z problemów, które przewiduję w takiej architekturze, jest słaby wgląd w to, jakie są zależności aplikacji. Załóżmy na przykład, że mam aplikację, która codziennie korzysta z jednego zestawu połączeń REST. Ta aplikacja korzysta również z drugiego zestawu połączeń REST, ale tylko raz na kwartał. Gdybym miał zeskanować dzienniki z ostatniego tygodnia, zobaczyłbym wszystkie codzienne połączenia, ale prawdopodobnie nie widziałbym połączeń kwartalnych. Jeśli chodzi o czas na refaktoryzację, połączenia kwartalne są narażone na wysokie ryzyko zerwania.

Jakie wzorce lub narzędzia można zastosować w celu zmniejszenia tego ryzyka i zapewnienia lepszego wglądu w zależności między luźno sprzężoną architekturą?

David mówi Przywróć Monikę
źródło
1
Właśnie dlatego luźne połączenie może być złe. Gdy nie ma zależności czasowych kompilacji, jedynym sposobem na wykrycie błędów i nigdy nie wychwycenie ich wszystkich jest użycie testów automatycznych. Rozwiązaniem jest pewien rodzaj testów automatycznych, które prawdopodobnie obejmują testy jednostkowe, a także testy integracyjne.
Frank Hileman,
@FrankHileman Testowanie oczywiście pomaga, ale trudno mi uwierzyć, że jest to jedyne dostępne rozwiązanie. Ponadto istnieje wiele języków, które nie mają sprawdzania czasu kompilacji (np. JS lub Python), więc nawet przy ścisłym sprzężeniu nadal występują problemy.
David mówi Przywróć Monikę
1
systemy typu statycznego mogą wychwycić dużą liczbę błędów podczas fazy kompilacji. Według mojej wiedzy jedyną rekompensatą za brak takiego systemu są testy automatyczne. Wykrywanie błędów statycznych za pomocą automatycznych prób lub po prostu kompilacji zawsze będzie bardziej niezawodne niż testy.
Frank Hileman,
Jednym z możliwych sposobów może być zaimplementowanie klienta API każdej usługi osobno, a także uwzględnienie tych klientów jako zależności projektu. Dzięki interfejsom API łatwiej byłoby również prześledzić, z której wersji usługi korzystamy.
Laiv
@Laiv Jestem szczególnie ciekawy usług RESTful, więc tak naprawdę nie jest to opcja, ponieważ każdy może wysyłać żądania HTTP mniej więcej.
David mówi Przywróć Monikę

Odpowiedzi:

4

Jakie wzory lub narzędzia można zastosować, aby zmniejszyć to ryzyko

Utrzymanie zgodności interfejsów API i możliwości biznesowych z poprzednimi wersjami.

zapewniają lepszy wgląd w zależności między luźno sprzężoną architekturą

Badania zdrowia.

Moja usługa jest klientem dla twoich miesięcznych możliwości API. Ale moja usługa jest klientem twojego interfejsu API za każdym razem, gdy moja usługa jest uruchomiona. Tak więc moja usługa budzi się co 10 minut lub cokolwiek innego, łączy się z miesięcznym interfejsem API i uruchamia protokół, aby upewnić się, że możliwości, których potrzebuje moja usługa, są nadal dostępne.

Więc twoje logi pokażą ci, jak często sprawdzana jest inna usługa, aby zobaczyć, czy każda konkretna usługa, którą oferujesz, jest nadal dostępna, tak jak pokazuje, jak często faktycznie używana jest każda z oferowanych usług.

VoiceOfUnreason
źródło
1

Istnieją co najmniej dwie lokalizacje, w których można znaleźć zależności:

  • Konfiguracja. Dostęp do zewnętrznych interfejsów API wymaga znajomości informacji o każdym z tych interfejsów API. Identyfikatory dostępu, tajne klucze, punkty końcowe. Wszystko to nie może być w kodzie, ponieważ takie informacje się zmienią. Jako przykład niedawno rozpocząłem migrację wszystkich moich mikrousług do protokołu SSL. Oznacza to, że każda usługa, która opiera się na migrowanej, powinna zostać ponownie skonfigurowana, aby wskazywała na https://wersję zamiast http://. Cieszę się, że punkty końcowe były w konfiguracji, a nie na stałe.

  • Interfejsy Nie masz dostępu do usługi bezpośrednio z kodu, ponieważ wersja interfejsu API ulegnie zmianie, a nawet możesz zdecydować się na przejście na inny interfejs API. Zamiast tego tworzysz warstwę abstrakcji i używasz zależności poprzez interfejs. Postępując zgodnie ze wspólną logiką podczas tworzenia tych interfejsów, możesz ułatwić sobie późniejsze wyszukiwanie zależności.

Jeśli chodzi o czas na refaktoryzację, połączenia kwartalne są narażone na wysokie ryzyko zerwania.

Do tego służą testy regresji.

Nie możesz po prostu patrzeć na kod, zmieniać go i ufać sobie, że nic nie zostało zepsute. To nie zadziała w architekturze mikrousług. To również nie zadziała w aplikacji monolitycznej. Kompilator może wychwycić niektóre błędy, które wprowadzisz podczas modyfikowania kodu. W niektórych językach, takich jak Haskell, kompilator może być bardzo zdolny i wychwytywać większość błędów; kompilatory dla języków głównego nurtu jednak niewiele dla ciebie zrobią. Jeśli nie masz testów, masz problemy. Obecność mikrousług jest nieistotna.

Arseni Mourzenko
źródło
-2

Interfejsy API REST są luźno określone, więc w pewnym momencie przydatne może być przejście do gRPC, google protobufs lub Thrift w celu zdefiniowania interfejsu RPC, a następnie jego wersji.

Patrick
źródło
2
To może być lepsze jako komentarz ... ale szczerze mówiąc, to niewiele wyjaśnia.
David mówi Przywróć Monikę
Słusznie. Reszta API nie ma określonej zależności czasu kompilacji od innej usługi, ponieważ połączenie między nimi jest tylko wywołaniem rest HTTP, czymś w rodzaju hosta i ścieżki. W przypadku gRPC, Protobuf lub Thrift definiowany jest interfejs, który służy do generowania kodu. Wygenerowany kod jest kompilowany i wersjonowany, a następnie twoja usługa (usługi) jest budowana na tych interfejsach. W rezultacie każda usługa jest wyraźnie zależna od jednego lub kilku innych interfejsów usług. Mam nadzieję, że to wyjaśnia moją odpowiedź!
Patrick