З цього посібника ви дізнаєтеся що таке мікросервіси Java, як їх проектувати та створювати. Також тут порушені питання про бібліотеки мікросервісів Java та доцільність застосування мікросервісів. Переклад та адаптація Java Microservices: A Practical Guide .
Мікросервіси Java: основи
Щоб зрозуміти мікросервіси, потрібно спочатку визначити, що не є. А чи не є ними “моноліт” — Java monolith: що це таке і які його переваги чи недоліки?Що таке Java-моноліт?
Уявіть, що ви працюєте у банку чи фінтех-стартапі. Ви надаєте користувачам мобільну програму, яку можна використовувати для відкриття нового банківського рахунку. У Java коді це призведе до наявності класу-контролера. Спрощено він виглядає так:@Controller
class BankController {
@PostMapping("/users/register")
public void register(RegistrationForm form) {
validate(form);
riskCheck(form);
openBankAccount(form);
// etc..
}
}
Вам потрібно, щоб контролер:
- Підтверджував форму реєстрації.
- Перевіряв ризики на адресау користувача, щоб вирішити, чи надавати йому банківський рахунок.
- Відкривав банківський рахунок.
BankController
буде упакований разом з рештою ваших вихідних файлів bank.jar або bank.war для розгортання - це і є старий добрий моноліт, що містить весь код, необхідний для роботи вашого банку. За грубими підрахунками, початковий розмір .jar (або .war) файлу складе від 1 до 100 МБ. Тепер ви можете просто запустити .jar файл на своєму сервері… і це все, що потрібно зробити для розгортання Java-додатки. Зображення, лівий прямокутник зверху: розгортання моно(літного) банку java -jar bank.jar (cp .war/.ear into appserver). Правий прямокутник: відкритий браузер.
У чому проблема з Java-монолітами?
По суті, в Java-монолітах немає нічого поганого. Однак досвід показав, що якщо у вас у проекті:- Працює багато програмістів / команд / консультантів.
- ...над одним і тим же монолітом під тиском замовників з вельми невиразними вимогами...
- протягом кількох років...
Як зменшити розмір моноліту Java?
Виникає природне питання: як зробити моноліт менше? Зараз ваш bank.jar працює на одній JVM, один процес на одному сервері. Ні більше, ні менше. І ось саме зараз на думку може спасти логічна думка: «Але ж служба перевірки ризиків може використовуватися й іншими відділами в моїй компанії! Вона не має безпосереднього відношення до моєї монолітної банківської програми! Можливо, чи варто вирізати її з моноліту і розгорнути, як окремий продукт? Тобто якщо говорити технічно, запустити його як окремий процес Java”.Що таке мікросервіс Java?
На практиці таке словосполучення означає, що тепер виклик методуriskCheck()
здійснюватиметься не з BankController: цей метод або bean-компонент з усіма його допоміжними класами буде переміщений у власний Maven- або Gradle-проект. Також його буде розгорнуто та поміщено під систему контролю версій незалежно від банківського моноліту. Однак весь цей процес вилучення не перетворює ваш новий модуль RiskCheck на мікросервіс як такий, оскільки визначення мікросервісу відкрито для інтерпретації. Це призводить до частих дискусій усередині команд та компаній.
- 5-7 класів у проекті – це мікро чи як?
- 100 чи 1000 класів... все ще мікро?
- Мікросервіс взагалі пов'язаний із кількістю класів чи ні?
- Назвемо всі сервіси, що окремо розгортаються, мікросервісами, незалежно від їх розмірів або меж домену.
- Подумаємо, як влаштувати міжсервісне спілкування. Нашим мікросервісам потрібні способи спілкування.
Як налагодити комунікацію між мікросервісами Java?
Загалом є два варіанти — синхронна та асинхронна комунікація.Синхронна комунікація: (HTTP)/REST
Зазвичай синхронізована комунікація між мікросервісами здійснюється через HTTP та REST-подібні сервіси, які повертають XML чи JSON. Зрозуміло, можуть бути й інші варіанти взяти хоча б Google Protocol Buffers . Якщо вам потрібна негайна відповідь, краще використовувати REST-комунікацію. У нашому прикладі саме так і потрібно робити, оскільки перевірка ризиків є обов'язковою перед відкриттям рахунку. Якщо немає перевірки ризиків, немає і рахунку. Інструменти обговоримо нижче, у розділі “ Які бібліотеки найкраще підходять для синхронних викликів Java REST ”.Обмін повідомленнями – асинхронна комунікація
Асинхронний мікросервісний зв'язок зазвичай здійснюється за допомогою обміну повідомленнями з реалізацією JMS та/або за допомогою протоколу, наприклад, AMQP . Ми тут написали "зазвичай" не просто так: скажімо, кількість інтеграцій електронною поштою/SMTP не можна недооцінювати. Використовуйте його тоді, коли вам не потрібна негайна відповідь. Наприклад, користувач натискає кнопку "купити зараз", а ви у свою чергу хочете згенерувати рахунок-фактуру. Цей процес, безумовно, не повинен відбуватися в рамках циклу запиту-відповіді користувача на покупку. Нижче описано, які інструменти найкраще підходять для асинхронного обміну повідомленнями Java .Приклад: виклик REST API у Java
Припустимо, ми обрали синхронну мікросервісну комунікацію. У такому разі наш Java-код (той, що ми наводабо вище) на низькому рівні виглядатиме приблизно так. (Під низьким рівнем тут ми розуміємо той факт, що для мікросервісної комунікації зазвичай створюються клієнтські бібліотеки, які абстрагують вас від реальних 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..
}
}
Виходячи з коду, стає ясно, що тепер нам потрібно розгорнути два Java-(мікро) сервіси, Bank та RiskCheck. У результаті у нас буде запущено два JVM-процеси. Ось і все, що вам потрібно для розробки проекту з мікросервісами Java: просто створюйте та розгортайте менші фрагменти (файли .jar або .war) замість одного монолітного. Залишається незрозумілою відповідь на питання, яким чином нам слід розрізати моноліт на мікросервіси? Наскільки дрібними мають бути ці шматочки, як визначити правильний розмір? Давайте перевіримо.
Архітектура Java Microservices
Насправді компанії розробляють мікросервісні проекти по-різному. Підхід залежить від того, чи намагаєтеся ви перетворити існуючий моноліт на проект із мікросервісами або ж починаєте проект з нуля.Від моноліту до мікросервісів
Одна з найлогічніших ідей - витягти мікросервіси з існуючого моноліту. Зверніть увагу, що приставка «мікро» тут насправді не означає, що вилучені сервіси будуть невеликими, це зовсім не обов'язково. Розгляньмо теоретичні основи.Ідея: розбити моноліт на мікросервіси
До легасі-проектів можна застосувати мікросервісний підхід. І ось чому:- Найчастіше такі проекти складно підтримувати/змінювати/розширювати.
- Усі, починаючи від розробників і до керівництва, хочуть спрощення.
- У вас (щодо) чіткі межі домену, тобто ви знаєте, що саме має робити ваше програмне забезпечення.
- Так, буде розумно виділити в окремий мікросервіс «Управління обліковими записами», обробку даних користувача (таких як імена, адресаи, номери телефонів).
- Або вищезгаданий «Модуль перевірки ризиків, який перевіряє рівні ризику користувача та може використовуватись багатьма іншими проектами або навіть відділами компанії.
- Або модуль виставлення рахунків, який надсилає рахунки у форматі PDF або поштою.
Втілення ідеї: нехай це зробить хтось інший
Описаний вище підхід відмінно виглядає на папері та UML-подібних діаграмах. Однак, все не так просто. Для його практичної реалізації потрібна серйозна технічна підготовка: прірва між розумінням того, що було б непогано витягти з моноліту і процесом вилучення — величезна. Більшість корпоративних проектів сягають стадії, коли розробники побоюються, скажімо, оновити 7-річну версію Hibernate до новішої. Разом з нею оновляться бібліотеки, проте існує неілюзорна небезпека щось поламати. І ось, ті ж розробники тепер повинні копатися в стародавньому легасі-коді з незрозумілими межами транзакцій бази даних і отримувати чітко визначені мікросервіси? Найчастіше це завдання дуже складна, її не вийде "вирішити" на дошці або на нарадах з архітектури. Процитую Twitter розробника @simonbrown: Я повторюватиму це знову і знову ... якщо люди не можуть правильно будувати моноліти, мікросервіси не допоможуть. Саймон БраунПроект "з нуля" на базі мікросервісної архітектури
У разі нових Java-проектів три нумеровані пункти з попередньої частини виглядають дещо інакше:- Ви починаєте з чистого листа, тому немає “багажу” для обслуговування.
- Розробники хотіли б, щоб у майбутньому все було просто.
- Проблема: у вас набагато туманніша картина меж доменів: ви не знаєте, що насправді має робити ваше програмне забезпечення (підказка: agile;))
Технічна мікросервісна архітектура
Перший пункт здається найбільш очевидним для розробників, однак є й ті, хто вкрай не рекомендує його. Хаді Харірі рекомендує рефакторинг "Extract Microservice" в IntelliJ. І хоча наступний приклад дуже спрощений, реалізації, які спостерігаються в реальних проектах, на жаль, не надто далеко від нього пішли. До мікросервісів@Service
class UserService {
public void register(User user) {
String email = user.getEmail();
String username = email.substring(0, email.indexOf("@"));
// ...
}
}
З substring-мікросервісом 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());
// ...
}
}
Таким чином, ви, по суті, включає виклик Java в виклик HTTP, без очевидних причин для цього. Одна з причин, однак, полягає у наступному: відсутність досвіду та спроба форсувати підхід на основі мікросервісів Java. Рекомендація: не робіть цього.
Workflow-орієнтована мікросервісна архітектура
p align="justify"> Наступним поширеним підходом є поділ мікросервісів Java на модулі на базі workflow. Приклад із реального життя: у Німеччині, коли ви звертаєтесь до (загальнодоступного) лікаря, він має записати ваше відвідування у своїй медичній CRM-системі. Щоб отримати оплату від страховки, він надішле дані про ваше лікування (і лікування інших пацієнтів) посереднику через XML. Посередник розгляне цей файл XML і (спрощено):- Перевірить, чи правильний XML-файл отримано.
- Перевірить правдоподібність процедур: скажімо, однорічна дитина, яка отримала три процедури чищення зубів за один день від лікаря-гінеколога виглядає дещо підозріло.
- Об'єднає XML із деякими іншими бюрократичними даними.
- Перешле XML-файл до страхової компанії, щоб ініціювати платежі.
- І перешле результат лікаря, забезпечивши його повідомленням «успіх» або «будь ласка, надішліть цей запис ще раз, як тільки це матиме сенс».
- Чи є потреба у розгортанні шести додатків для обробки одного XML-файлу?
- Чи ці мікросервіси незалежні один від одного? Чи можуть вони бути розгорнуті незалежно один від одного? З різними версіями та схемами API?
- Що робить мікросервіс правдоподібності інформації, якщо мікросервіс перевірки не працює? Система все ще працює?
- Чи поділяють ці мікросервіси одну й ту саму базу даних (їм, безумовно, потрібні деякі загальні дані в таблицях БД), чи кожен має свою власну?
- … і багато іншого.
- Вам потрібно не просто розгорнути одну програму, а як мінімум шість.
- Можливо, навіть потрібно розгорнути кілька баз даних, залежно від того, як далеко ви хочете заглибитись у мікросервісну архітектуру.
- Потрібно стежити, щоб кожна система працювала в режимі онлайн, причому працювала нормально.
- Необхідно переконатися, що ваші виклики між мікросервісами дійсно стійкі (див. Як зробити мікросервіс Java стійким?).
- І все інше, що має на увазі це налаштування — від локальних налаштувань розробки до інтеграційного тестування.
- Якщо ви не Netflix (скоріше за все, ви не Netflix) ...
- Якщо ви не маєте надсильних навичок роботи, при яких ви відкриваєте середовище розробки, а воно викликає хаосну мавпу, яка відкидає вашу виробничу базу даних, яка легко відновлюється через 5 секунд.
- або ви почуваєтеся як @monzo і готові випробувати 1500 мікросервісів просто тому, що можете.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ