Sposoby udostępniania DTO w mikrousługach?

33

Mój scenariusz jest następujący.

Projektuję system zaprojektowany do odbierania danych z różnego rodzaju czujników, a następnie ich konwersji, a następnie przechowywania w celu późniejszego wykorzystania przez różne usługi front-end i analityczne.

Staram się zaprojektować każdą usługę tak, aby była jak najbardziej niezależna, ale mam pewne problemy. Zespół zdecydował się na DTO, którego chcielibyśmy użyć. Usługi skierowane na zewnątrz (odbiorcy danych z czujników) otrzymają dane na swój unikalny sposób, a następnie przekonwertują je na obiekt JSON (DTO) i wyślą do brokera komunikatów. Konsumenci wiadomości będą wtedy dokładnie wiedzieć, jak odczytać komunikaty danych czujnika.

Problem polega na tym, że używam tego samego DTO w kilku różnych usługach. Aktualizacja musi zostać wdrożona w wielu lokalizacjach. Oczywiście zaprojektowaliśmy to w taki sposób, że kilka dodatkowych lub brakujących pól w DTO tutaj i nie ma większego problemu, dopóki usługi nie zostaną zaktualizowane, ale wciąż mnie to denerwuje i sprawia, że ​​czuję się jakbym popełniać błąd. Może łatwo przerodzić się w ból głowy.

Czy zamierzam źle zaprojektować system? Jeśli nie, jakie są sposoby na to, a przynajmniej na złagodzenie moich obaw?

nbaughman
źródło
Jakiego rodzaju DTO udostępniasz i jakiego protokołu używasz między usługami? Można na przykład udostępnić protoplik gRPC lub avroschemat dla Kafki i wygenerować DTO w obu usługach, ale nie udostępniłbym wspólnej biblioteki między dwoma projektami.
Vincent Savard
Zakodowane ciągi JSON i AMQP. Wolałbym nie używać niczego specyficznego dla języka.
nbaughman

Odpowiedzi:

38

Moja rada? Nie udostępniaj tych DTO między aplikacjami w jakiejkolwiek bibliotece. A przynajmniej nie rób tego teraz.

Wiem, wydaje się bardzo sprzeczna z intuicją. Kopiujesz kod, prawda? Ale to nie jest reguła biznesowa, więc możesz być bardziej elastyczny.

Usługa wysyłająca DTO musi być sztywna w umowie dotyczącej wiadomości, podobnie jak Rest API. Usługa nie może zmienić DTO w sposób, który mógłby zepsuć inne usługi, które już wykorzystują informacje z DTO.

Po dodaniu nowego pola do DTO aktualizujesz tylko inne usługi korzystające z tego DTO, jeśli potrzebują nowego pola. W przeciwnym razie zapomnij o tym. Używając JSON jako typu zawartości, możesz elastycznie tworzyć i wysyłać nowe atrybuty bez zepsucia kodu usług, które nie mapują tych nowych pól w jego rzeczywistych wersjach DTO.

Ale jeśli ta sytuacja naprawdę Cię niepokoi, możesz przestrzegać Reguły Trzech :

Podczas ponownego użycia istnieją dwie „zasady trzech”: (a) trzy razy trudniej jest zbudować komponenty wielokrotnego użytku niż komponenty jednorazowego użytku, oraz (b) przetestować komponent wielokrotnego użytku w trzech różnych zastosowaniach, zanim będzie on wystarczająco ogólny przyjąć do biblioteki ponownego wykorzystania.

Spróbuj więc poczekać trochę dłużej, zanim udostępnisz to DTO między usługami.

Dherik
źródło
1
Bardzo mile widziane. To naprawdę jedna z niewielu głównych kwestii, które naprzód. Nie dość, że nie mogę zasnąć w nocy, ale wystarczająco mnie martwi.
nbaughman
4
Duplikaty DTO (w różnych i bardzo niezależnych usługach) nie naruszają DRY. to jest to!
Laiv
3
Prawdopodobnie nie ma powodu, aby nie kopiować kodu źródłowego DTO bezpośrednio z jednego projektu do drugiego, jako jednorazowa operacja, chociaż wówczas wszelkie części niewymagane w nowym projekcie powinny prawdopodobnie zostać usunięte.
bdsl
1
Nawet cała usługa może zostać usunięta, nie powodując większych problemów w całym systemie. Idealnie.
Laiv
4
Aby wyjaśnić istotę odpowiedzi, przy opracowywaniu mikrousług, każda usługa powinna być rozwijana tak, jakby nie wiedziała o innych usługach, z wyjątkiem faktycznych umów, które mogą wymagać.
Jonathan van de Veen
12

Jeśli chodzi o Microservices, cykle rozwoju usług również powinny być niezależne. *

Różne zespoły SLDC i różne zespoły programistów

w prawdziwym systemie MS może być kilka zespołów zaangażowanych w rozwój ekosystemu, z których każdy odpowiada za jedną lub więcej usług. Z kolei zespoły te mogą znajdować się w różnych biurach, miastach, krajach, planach… Być może nawet się nie znają, co bardzo utrudnia dzielenie się wiedzą lub kodem (jeśli to możliwe). Ale może to być bardzo wygodne, ponieważ wspólny kod oznacza również rodzaj rozumowania dzielenia się i ważne jest, aby pamiętać, że cokolwiek ma sens dla konkretnego zespołu, nie musi robić tego dla innego zespołu. Na przykład, biorąc pod uwagę klienta DTO , może być inaczej w zależności od usługi w grze, ponieważ klienci są interpretowani (lub widziani) inaczej niż każda usługa.

Różne potrzeby, różne technologie

Izolowane SLDC pozwalają również zespołom wybrać stos, który najlepiej odpowiada ich potrzebom. Nałożenie DTO zaimplementowanych w określonej technologii ogranicza możliwości wyboru zespołów.

DTO nie są ani zasadami biznesowymi, ani umowami o świadczenie usług

Czym naprawdę są DTO? Proste obiekty bez innego celu niż przenoszenie danych z jednej strony na drugą. Torby z getterami i seterami. Nie jest to „wiedza”, którą warto ponownie wykorzystać, ponieważ w ogóle nie ma wiedzy. Ich zmienność czyni ich również złymi kandydatami do połączenia.

W przeciwieństwie do tego, co stwierdził Dherik, usługa musi mieć możliwość zmiany DTO bez konieczności dokonywania zmian w innych usługach w tym samym czasie. Usługi powinny być tolerancyjnymi czytelnikami, tolerancyjnymi pisarzami i odpornymi na błędy . W przeciwnym razie powodują sprzężenie w taki sposób, że architektura usługi nie ma sensu. Jeszcze raz, w przeciwieństwie do odpowiedzi Dherika, jeśli trzy usługi potrzebują dokładnie tych samych DTO, prawdopodobnie coś poszło nie tak podczas rozkładu usług.

Różny biznes, różne interpretacje

Chociaż mogą istnieć (i będą) przekrojowe koncepcje między usługami, nie oznacza to, że musimy narzucić model kanoniczny, aby zmusić wszystkie usługi do interpretowania ich w ten sam sposób.

Studium przypadku

Powiedzmy, że nasza firma ma trzy działy: obsługi klienta , sprzedaży i wysyłki . Powiedz, że każda z tych wersji udostępnia jedną lub więcej usług.

Obsługa klienta, ze względu na język swojej domeny , wdraża usługi wokół koncepcji klientów, gdzie klientamiosoby . Na przykład klienci są modelowani jako imię , nazwisko , wiek , płeć , adres e-mail , telefon itp.

Powiedzmy teraz, że sprzedaż i wysyłka modelują również swoje usługi zgodnie z ich językami domen. W tych językach pojawia się również klient koncepcyjny, ale z subtelną różnicą. Dla nich klienci nie są (koniecznie) osobami . Do sprzedaży , klienci są numer dokumentu karty kredytowej i adres rozliczeniowy , o wysyłce do pełnej nazwy i adresu wysyłki za.

Jeśli zmusimy sprzedaży i wysyłki do przyjęcia kanoniczny model danych Obsługa klienta , jesteśmy zmuszając je do czynienia z niepotrzebnych danych, które może skończyć się wprowadzenie niepotrzebnej złożoności jeśli muszą utrzymać całą reprezentację i utrzymać klienta danych w synchronizacji z obsługą klienta .

Powiązane linki


* Oto, na czym polega siła tej architektury

Laiv
źródło
Dziękuję Ci! Studia przypadków są w rzeczywistości tym, co pomogło mi ustalić, czy podzielić się DTO, czy nie. Teraz jestem pewien, dlaczego nie chciałem się nimi dzielić.
Igor
8

Staram się zaprojektować każdą usługę tak, aby była jak najbardziej niezależna

Powinieneś publikować wydarzenia . Zdarzenia to pewien rodzaj komunikatów, które stanowią solidny fakt na temat czegoś, co wydarzyło się w określonym momencie.

Każda usługa powinna mieć bardzo dobrze określoną odpowiedzialność i powinna być odpowiedzialna za publikowanie wydarzeń związanych z tą odpowiedzialnością.

Ponadto chcesz, aby Twoje wydarzenia reprezentowały wydarzenia związane z biznesem, a nie wydarzenia techniczne. Np. Wolę OrderCancelledwydarzenie od OrderUpdatedz status: "CANCELLED".

W ten sposób, gdy usługa musi zareagować na anulowane zamówienie, musi po prostu wysłuchać określonego rodzaju wiadomości, która przenosi tylko dane istotne dla tego zdarzenia. Np. OrderCancelledPrawdopodobnie potrzebuje tylko order_id. Jakakolwiek usługa, która musi na to zareagować, zapisała już wszystko, co musi wiedzieć o zamówieniu we własnym magazynie danych.

Ale jeśli usługa miałaby tylko OrderUpdatedzdarzenia do wysłuchania, musiałaby zinterpretować przebieg zdarzeń, a teraz była zależna od zamówienia dostawy, aby mogła zostać poprawnie zakończona po anulowaniu zamówienia.

W twoim przypadku, jednak, jak Twój publikujemy dane czujnika, to może mieć sens mieć usługę, słuchać wydarzeń i opublikować nowy strumień zdarzeń „biznes”, na przykład TemperatureThresholdExceeded, TemperatureStabilised.

I uważaj na tworzenie zbyt wielu mikrousług. Mikrousługi mogą być świetnym sposobem na enkapsulowanie złożoności, ale jeśli nie odkryjesz odpowiednich granic usług, twoja złożoność polega na integracji usług. I to jest koszmar do utrzymania.

Lepiej mieć za mało, za dużych usług, niż mieć za dużo, za małych usług.

Pete
źródło
Zdecydowanie się zgadzam. Dane czujnika przechodzą bezpośrednio do mikrousługi, która analizuje komunikat i przekształca go w format uzgodniony dla całej organizacji przed opublikowaniem go brokerowi. Będziemy mieć niektóre usługi, które czytają wiadomość i utrwalają ją w bazie danych, oraz inne, które wykonują analizę wiadomości i robią z nią własne rzeczy. Każda usługa ze swojej natury nie ma wiele do zrobienia, co prowadzi (miejmy nadzieję) do dość prostych usług.
nbaughman
2
@ Nickdb93 - W twoim przypadku, gdy publikujesz dane z czujników, warto mieć usługę, słuchać wydarzeń i publikować nowy strumień „zdarzeń biznesowych”, np. TemperatureThresholdExceeded, TemperatureStabilised. (dodano do odpowiedzi)
Pete