W tym przewodniku dowiesz się, czym są mikroserwisy Java, jak je projektować i tworzyć. Obejmuje także pytania dotyczące bibliotek mikrousług Java i możliwości korzystania z mikrousług. Tłumaczenie i adaptacja mikrousług Java: praktyczny przewodnik .
Mikrousługi Java: podstawy
Aby zrozumieć mikrousługi, musisz najpierw zdefiniować, czym one nie są. Czy nie jest to „monolit” – monolit Java: czym jest i jakie są jego zalety i wady?Co to jest monolit Java?
Wyobraź sobie, że pracujesz dla banku lub startupu fintech. Udostępniasz użytkownikom aplikację mobilną, za pomocą której mogą otworzyć nowe konto bankowe. W kodzie Java spowoduje to obecność klasy kontrolera. W uproszczeniu wygląda to tak:@Controller
class BankController {
@PostMapping("/users/register")
public void register(RegistrationForm form) {
validate(form);
riskCheck(form);
openBankAccount(form);
// etc..
}
}
Potrzebujesz kontrolera do:
- Potwierdzono formularz rejestracyjny.
- Sprawdziłem ryzyko związane z adresem użytkownika, aby zdecydować, czy udostępnić mu konto bankowe.
- Otworzył konto bankowe.
BankController
zostanie spakowana wraz z resztą źródeł w pliku bank.jar lub bank.war w celu wdrożenia — jest to stary, dobry monolit zawierający cały kod potrzebny do uruchomienia banku. Z grubsza szacuje się, że początkowy rozmiar pliku .jar (lub .war) będzie wynosić od 1 do 100 MB. Teraz możesz po prostu uruchomić plik .jar na swoim serwerze... i to wszystko, co musisz zrobić, aby wdrożyć aplikację Java. Zdjęcie, lewy górny prostokąt: wdrożenie mono(litycznego) banku java -jar bank.jar (cp .war/.ear do serwera aplikacji). Prawy prostokąt: otwórz przeglądarkę.
Jaki jest problem z monolitami Java?
Nie ma nic złego w monolitach Java. Jednak doświadczenie pokazało, że jeśli w Twoim projekcie:- Pracuje wielu programistów/zespołów/konsultantów...
- ...nad tym samym monolitem pod presją klientów o bardzo niejasnych wymaganiach...
- w ciągu kilku lat...
Jak zmniejszyć rozmiar monolitu Java?
Powstaje naturalne pytanie: jak zmniejszyć monolit? W tej chwili Twój plik bank.jar działa na jednej maszynie JVM, jeden proces na jednym serwerze. Nie więcej nie mniej. I w tej chwili może przyjść nam do głowy logiczna myśl: „Ale z usługi weryfikacji ryzyka mogą korzystać inne działy w mojej firmie! Nie jest to bezpośrednio powiązane z moją monolityczną aplikacją bankową! Może warto go wyciąć z monolitu i wstawić jako osobny produkt? Oznacza to, technicznie rzecz biorąc, uruchomienie go jako oddzielnego procesu Java.Co to jest mikrousługa Java?
W praktyce to zdanie oznacza, że teraz wywołanie metodyriskCheck()
nie będzie wykonane z BankControllera: ta metoda lub komponent bean wraz ze wszystkimi jej klasami pomocniczymi zostanie przeniesiony do własnego projektu Maven lub Gradle. Zostanie również wdrożony i objęty kontrolą wersji niezależnie od monolitu bankowego. Jednakże cały ten proces ekstrakcji nie powoduje przekształcenia nowego modułu RiskCheck w mikrousługę samą w sobie, ponieważ definicja mikrousługi jest otwarta na interpretację. Prowadzi to do częstych dyskusji w zespołach i firmach.
- Czy 5-7 zajęć w projekcie jest mikro czy co?
- 100 czy 1000 zajęć... nadal mikro?
- Czy mikrousługi są ogólnie powiązane z liczbą klas, czy nie?
- Nazwijmy wszystkie oddzielnie wdrożone usługi mikrousługami, niezależnie od ich rozmiaru i granic domeny.
- Zastanówmy się, jak zorganizować komunikację między służbami. Nasze mikrousługi potrzebują sposobów komunikowania się ze sobą.
Jak nawiązać komunikację między mikroserwisami Java?
Ogólnie rzecz biorąc, istnieją dwie opcje - komunikacja synchroniczna i asynchroniczna.Komunikacja synchroniczna: (HTTP)/REST
Zazwyczaj zsynchronizowana komunikacja między mikrousługami odbywa się za pośrednictwem usług HTTP i REST, które zwracają XML lub JSON. Oczywiście mogą istnieć inne opcje - weź przynajmniej Bufory protokołu Google . Jeśli potrzebujesz natychmiastowej reakcji, lepiej skorzystać z komunikacji REST. W naszym przykładzie właśnie to należy zrobić, ponieważ przed otwarciem konta wymagana jest weryfikacja ryzyka. Jeśli nie ma kontroli ryzyka, nie ma konta. Narzędzia omówimy poniżej, w sekcji „ Które biblioteki są najlepsze do synchronicznych wywołań Java REST ”.Przesyłanie wiadomości — komunikacja asynchroniczna
Asynchroniczną komunikację mikrousługową zwykle realizuje się poprzez wymianę komunikatów z implementacją JMS i/lub przy użyciu protokołu, takiego jak AMQP . Nie bez powodu napisaliśmy tutaj „zwykle”: powiedzmy, że nie można niedoceniać liczby integracji poczty e-mail/SMTP. Użyj go, gdy nie potrzebujesz natychmiastowej reakcji. Przykładowo, użytkownik klika przycisk „kup teraz”, a Ty z kolei chcesz wygenerować fakturę. Proces ten z pewnością nie powinien zachodzić w cyklu żądanie zakupu-odpowiedź użytkownika. Poniżej opiszemy, które narzędzia są najlepsze do asynchronicznego przesyłania komunikatów w języku Java .Przykład: wywołanie API REST w Javie
Załóżmy, że wybieramy synchroniczną komunikację mikrousług. W tym przypadku nasz kod Java (ten, który przedstawiliśmy powyżej) na niskim poziomie będzie wyglądał mniej więcej tak. (przez niski poziom rozumiemy tutaj fakt, że w przypadku komunikacji mikrousług zwykle tworzone są biblioteki klienckie, które odrywają Cię od rzeczywistych wywołań HTTP).@Controller
class BankController {
@Autowired
private HttpClient httpClient;
@PostMapping("/users/register")
public void register(RegistrationForm form) {
validate(form);
httpClient.send(riskRequest, responseHandler());
setupAccount(form);
// etc..
}
}
Na podstawie kodu staje się jasne, że musimy teraz wdrożyć dwie (mikro) usługi Java, Bank i RiskCheck. W rezultacie będziemy mieć uruchomione dwa procesy JVM. To wszystko, czego potrzebujesz, aby opracować projekt mikrousług Java: po prostu zbuduj i wdróż mniejsze fragmenty (pliki .jar lub .war) zamiast jednej monolitycznej. Odpowiedź na pytanie pozostaje niejasna: jak podzielić monolit na mikroserwisy? Jak małe powinny być te kawałki, jak określić właściwy rozmiar? Sprawdźmy.
Architektura mikrousług Java
W praktyce firmy rozwijają projekty mikroserwisowe na różne sposoby. Podejście zależy od tego, czy próbujesz przekształcić istniejący monolit w projekt mikrousług, czy zaczynasz projekt od zera.Od monolitu do mikrousług
Jednym z najbardziej logicznych pomysłów jest wyodrębnienie mikrousług z istniejącego monolitu. Należy zauważyć, że przedrostek „mikro” w tym przypadku nie oznacza w rzeczywistości, że wyodrębnione usługi będą naprawdę niewielkie; niekoniecznie tak jest. Spójrzmy na tło teoretyczne.Pomysł: rozbić monolit na mikrousługi
Podejście oparte na mikrousługach można zastosować w przypadku starszych projektów. I własnie dlatego:- Najczęściej takie projekty są trudne w utrzymaniu/zmianie/rozbudowie.
- Wszyscy, od programistów po zarząd, chcą uproszczeń.
- Masz (stosunkowo) jasne granice domeny, co oznacza, że dokładnie wiesz, co powinno robić Twoje oprogramowanie.
- Rozsądne byłoby zatem wydzielenie przetwarzania danych użytkowników (takich jak nazwiska, adresy, numery telefonów) do osobnej mikrousługi „Zarządzanie kontem”.
- Albo wspomniany wcześniej „Moduł Kontroli Ryzyka”, który sprawdza poziom ryzyka użytkownika i może być wykorzystywany przez wiele innych projektów, a nawet działów firmy.
- Lub moduł fakturowania, który wysyła faktury w formacie PDF lub pocztą.
Realizacja pomysłu: pozwól to zrobić komuś innemu
Opisane powyżej podejście wygląda świetnie na papierze i diagramach przypominających UML. Jednak nie wszystko jest takie proste. Jego praktyczne wdrożenie wymaga poważnego przygotowania technicznego: rozbieżność między naszym rozumieniem tego, co fajnie byłoby wydobyć z monolitu, a samym procesem ekstrakcji jest ogromna. Większość projektów korporacyjnych osiąga etap, w którym programiści boją się, powiedzmy, uaktualnić 7-letnią wersję Hibernate do nowszej. Biblioteki będą aktualizowane wraz z nim, ale istnieje realne niebezpieczeństwo, że coś zepsuje. Zatem ci sami programiści muszą teraz przekopywać się przez starożytny kod z niejasnymi granicami transakcji w bazie danych i wyodrębniać dobrze zdefiniowane mikrousługi? Najczęściej problem ten jest bardzo złożony i nie da się go „rozwiązać” ani na tablicy, ani na spotkaniach poświęconych architekturze. Cytując twórcę Twittera @simonbrown: Będę to powtarzać w kółko… jeśli ludzie nie potrafią poprawnie budować monolitów, mikrousługi nie pomogą. Simona BrownaProjekt od podstaw w oparciu o architekturę mikroserwisową
W przypadku nowych projektów Java trzy ponumerowane elementy z poprzedniej części wyglądają nieco inaczej:- Zaczynasz z czystym kontem, więc nie musisz utrzymywać żadnego „bagażu”.
- Twórcy chcą, aby w przyszłości wszystko było proste.
- Problem: Masz znacznie bardziej niejasny obraz granic domen: nie wiesz, co tak naprawdę ma robić Twoje oprogramowanie (wskazówka: zwinny ;))
Architektura techniczna mikrousług
Pierwszy punkt wydaje się być najbardziej oczywisty dla deweloperów, choć są też tacy, którzy zdecydowanie go odradzają. Hadi Hariri zaleca refaktoryzację „Extract Microservice” w IntelliJ. I choć poniższy przykład jest bardzo uproszczony, to realizacje zaobserwowane w rzeczywistych projektach niestety nie odbiegają od niego zbytnio. Przed mikroserwisami@Service
class UserService {
public void register(User user) {
String email = user.getEmail();
String username = email.substring(0, email.indexOf("@"));
// ...
}
}
Z podciągiem mikrousługi Java
@Service
class UserService {
@Autowired
private HttpClient client;
public void register(User user) {
String email = user.getEmail();
//теперь вызываем substring microservice via http
String username = httpClient.send(substringRequest(email), responseHandler());
// ...
}
}
Zasadniczo zawijasz wywołanie metody Java w wywołaniu HTTP, bez wyraźnego powodu. Jest jednak jeden powód: brak doświadczenia i próba narzucenia podejścia opartego na mikroserwisach Java. Zalecenie: nie rób tego.
Architektura mikrousług zorientowana na przepływ pracy
Kolejnym powszechnym podejściem jest podzielenie mikrousług Java na moduły oparte na przepływie pracy. Przykład z życia wzięty: w Niemczech, gdy udajesz się do lekarza (publicznego), musi on zarejestrować Twoją wizytę w swoim medycznym systemie CRM. Aby otrzymać zapłatę z ubezpieczenia, prześle on dane dotyczące Twojego leczenia (i leczenia innych pacjentów) do pośrednika poprzez XML. Broker sprawdzi ten plik XML i (w uproszczeniu):- Sprawdzi, czy otrzymano poprawny plik XML.
- Sprawdzi wiarygodność zabiegów: powiedzmy, roczne dziecko, które w ciągu jednego dnia otrzymało od ginekologa trzy zabiegi czyszczenia zębów, wygląda nieco podejrzanie.
- Połączy XML z innymi biurokratycznymi danymi.
- Prześle plik XML do firmy ubezpieczeniowej w celu zainicjowania płatności.
- I wyśle wynik do lekarza, przekazując mu komunikat „sukces” lub „proszę o ponowne przesłanie tego nagrania, gdy tylko będzie to miało sens”.
- Czy do przetworzenia jednego pliku XML konieczne jest wdrożenie sześciu aplikacji?
- Czy te mikrousługi są rzeczywiście od siebie niezależne? Czy można je wdrażać niezależnie od siebie? Z różnymi wersjami i schematami API?
- Co robi mikrousługa wiarygodności, jeśli mikrousługa weryfikacyjna nie działa? Czy system nadal działa?
- Czy te mikrousługi korzystają z tej samej bazy danych (z pewnością potrzebują wspólnych danych w tabelach DB), czy też każdy z nich ma własną?
- … i wiele więcej.
- Nie musisz wdrożyć tylko jednej aplikacji, ale co najmniej sześciu.
- Może nawet zaistnieć potrzeba wdrożenia wielu baz danych, w zależności od tego, jak daleko chcesz zagłębić się w architekturę mikrousług.
- Musisz upewnić się, że każdy system jest online i działa poprawnie.
- Musisz upewnić się, że połączenia między mikrousługami są naprawdę odporne (zobacz Jak zapewnić odporność mikrousług Java?).
- I wszystko inne, co oznacza ta konfiguracja - od lokalnych ustawień programistycznych po testowanie integracji.
- Jeśli nie jesteś Netfliksem (prawdopodobnie nie jesteś Netfliksem)...
- Chyba, że masz super silne umiejętności pracy, gdy otwierasz środowisko programistyczne i powoduje to małpę chaosu, która wyrzuca produkcyjną bazę danych, którą można łatwo przywrócić w 5 sekund.
- lub czujesz się jak @monzo i chcesz wypróbować 1500 mikrousług tylko dlatego, że możesz.
GO TO FULL VERSION