Взаємодія мікросервісів: Request/Response | WebCraft

Взаємодія мікросервісів: Request/Response — коли синхронність має сенс

Коли мікросервіси почали масово замінювати моноліти, одним із перших підходів до їхньої взаємодії став Request/Response. Це знайомий, простий і добре документований механізм: один сервіс надсилає запит — інший обробляє його та повертає відповідь. Наприклад: користувач натискає «замовити», `order-service` запитує у `inventory-service`, чи є товар у наявності, отримує відповідь і продовжує процес. Але чи завжди цей підхід доречний? Коли він працює добре, а коли створює проблеми? У цій статті ми детально розглянемо модель **Request/Response**, її реалізацію на Java (Spring Boot) та JavaScript (Node.js/React), типові помилки, оптимізацію та порівняння з альтернативними підходами. Це керівництво для розробників, які хочуть зрозуміти, як організувати взаємодію між сервісами без втрати продуктивності та надійності.

Зміст статті:

Що таке Request/Response у мікросервісах?

Це **синхронна взаємодія**, при якій один сервіс (клієнт) надсилає HTTP-запит до іншого (сервер), чекає на відповідь і лише потім продовжує виконання. Найчастіше використовується REST API поверх HTTP.

Основні характеристики

  • Синхронність: клієнт блокується, поки не отримає відповідь
  • Простота: добре знайомий підхід (як веб-браузер і сервер)
  • Чіткий контракт: OpenAPI/Swagger дозволяє точно описати API
  • Швидкий результат: швидко реалізувати для MVP

Типові сценарії використання

👉 Приклади:

  • Автентифікація: `auth-service` перевіряє токен від `user-service`
  • Пошук товару: `catalog-service` запитує дані про ціну у `pricing-service`
  • Створення замовлення: `order-service` запитує доступність у `inventory-service`

Request/Response — це «Hello World» взаємодії між сервісами. Просто, зрозуміло, але не завжди безпечне.

⚠️ Важливо: синхронні виклики можуть призвести до **ламцюгового відмовлення**, якщо один сервіс зависне.

Як працює взаємодія за схемою запит-відповідь?

Процес виглядає так: клієнт формує запит → відправляє його по HTTP → сервер обробляє → повертає відповідь (JSON) → клієнт реагує.

Життєвий цикл одного запиту

  1. Користувач створює замовлення у UI
  2. Frontend надсилає POST /api/orders до `order-service`
  3. `order-service` робить GET /api/inventory/{id} до `inventory-service`
  4. `inventory-service` перевіряє базу даних
  5. Повертає { "available": true, "qty": 5 }
  6. `order-service` створює замовлення та повертає 201 Created

Формати даних

  • JSON — найпоширеніший формат
  • Protobuf — для високої продуктивності (менший розмір, швидше парсинг)
  • XML — рідше, у legacy-системах

⚡ Наприклад: заміна JSON на Protobuf у внутрішніх сервісних викликах скоротила час відповіді на 40% у проекті з високим навантаженням.

Навіть найпростіший запит може стати «бутлячим місцем», якщо сервіс-отримувач повільний або недоступний.

⚠️ Важливо: завжди встановлюйте **таймаути** (напр., 5 секунд) і **retries** (напр., 2 рази).

Реалізація на Java (Spring Boot)

Spring Boot пропонує кілька способів для виклику інших сервісів: `RestTemplate`, `WebClient`, `OpenFeign`.

Варіант 1: RestTemplate (синхронний)

@Service

public class InventoryClient {

@Autowired

private RestTemplate restTemplate;

public boolean isAvailable(String productId) {

String url = "http://inventory-service/api/inventory/" + productId;

try {

ResponseEntity response =

restTemplate.getForEntity(url, InventoryResponse.class);

return response.getBody().isAvailable();

} catch (HttpClientErrorException e) {

throw new ServiceUnavailableException("Inventory service error");

}

}

}

Варіант 2: OpenFeign (рекомендовано)

@FeignClient(name = "inventory-service", url = "http://inventory-service")

public interface InventoryClient {

@GetMapping("/api/inventory/{id}")

InventoryResponse getInventory(@PathVariable("id") String productId);

}

👉 Плюси: автоматичне створення клієнта, інтеграція з Ribbon/Eureka, легке тестування.

⚠️ Важливо: додайте `@HystrixCommand` або `Resilience4j` для fallback-логіки, якщо сервіс недоступний.

Реалізація на JavaScript (Node.js + React)

Backend: Node.js (Express + Axios)

// order-service (Node.js)

const axios = require('axios');

app.post('/orders', async (req, res) => {

const { productId } = req.body;

try {

const response = await axios.get(

`http://inventory-service:3001/inventory/${productId}`,

{ timeout: 5000 }

);

if (!response.data.available) {

return res.status(400).json({ error: "Not in stock" });

}

// Create order...

res.status(201).json({ orderId: "..." });

} catch (error) {

res.status(503).json({ error: "Inventory service unavailable" });

}

});

Frontend: React (fetch / axios)

// React Component

const createOrder = async () => {

try {

const response = await axios.post('/api/orders', { productId: "p1" });

console.log("Order created:", response.data.orderId);

} catch (error) {

alert("Помилка створення замовлення");

}

};

JavaScript дає гнучкість, але вимагає обережності: не забувайте про обробку помилок, таймаути та лоадери в UI.

👉 Приклад: ми додали спинер у React, який показується, коли `order-service` чекає відповіді від `payment-service`.

Переваги та недоліки

ПеревагиНедоліки
Простота розумінняСинхронність = ризик блокування
Легко тестувати (POSTMAN, curl)Ланцюги залежностей (A→B→C)
Добре документовані API (Swagger)Вразливість до простоїв
Швидкий старт для MVPСкладно масштабувати при високому навантаженні

Request/Response — це як автомобіль: зручно, швидко, але не підходить для кожного маршруту.

⚠️ Важливо: не використовуйте синхронні виклики для довгих операцій (напр., генерація звіту). Краще — event-driven або polling.

Порівняння з Event-Driven Architecture

КритерійRequest/ResponseEvent-Driven
Тип взаємодіїСинхроннийАсинхронний
Час відповідіМиттєвийІз затримкою
ЗалежністьВисока (direct call)Низька (через чергу)
СкладністьНизькаВисока (Kafka, RabbitMQ)
ПрикладПеревірка наявностіНадсилання email після оплати

Коли що використовувати?

  • Request/Response: коли потрібна відповідь «тут і зараз»
  • Event-Driven: коли важлива надійність, автономність, масштабованість

👉 Приклад: ми використовуємо Request/Response для перевірки наявності, але Event-Driven — для оповіщення, бухгалтерії та аналітики.

⚠️ Важливо: найкращі системи використовують **гибридний підхід**.

Практичні приклади з життя

Кейс 1: Онлайн-магазин (Успіх)

Використовуємо Request/Response між `order-service` та `inventory-service`. Додано таймаути (3 сек), retry (2 рази), fallback («перевіримо пізніше»). Конверсія не впала, система стабільна.

Кейс 2: Фінансова платформа (Хиба)

Сервіс `risk-analysis` синхронно запитував 5 інших сервісів. Середній час відповіді — 8 секунд. Ми переробили на event-driven: тепер аналіз виконується у фоні, користувач отримує статус через WebSocket.

Кейс 3: CRM (Гібрид)

UI → `api-gateway` → `contact-service` (Request/Response). Після збереження — подія `ContactUpdated` → `analytics-service`, `email-service`. Баланс між швидкістю та надійністю.

Правильна взаємодія — це не про технологію, а про розуміння бізнес-потреб.

Часто задавані питання (FAQ)

Чи можна використовувати Request/Response у великих системах?

Так, але обмежено. Для критичних, часових операцій — так. Для довгих процесів — краще event-driven.

Як уникнути cascade failure?

Використовуйте: таймаути, retries, circuit breaker (Resilience4j), fallback-відповіді.

Чи безпечний HTTP між сервісами?

Тільки через HTTPS (mTLS) або всередині закритої мережі (VPC). Для чутливих даних — додаткова шифрація.

Чи можна комбінувати Request/Response з event-driven?

Так, і це найкраща практика. Наприклад: синхронна валідація + асинхронна обробка.

Як тестувати взаємодію між сервісами?

👉 Засоби: Contract Testing (Pact), MockServer, TestContainers. Тестуйте не лише успішний сценарій, а й помилки, таймаути, відмови.

Висновки

Request/Response — це **фундаментальний механізм взаємодії мікросервісів**, який залишається актуальним завдяки простоті, швидкості та зрозумілості.

  • Використовуйте його для синхронних, часових операцій
  • Додавайте таймаути, retries, fallback
  • Обирайте OpenFeign (Java) або Axios (JS) для реалізації
  • Уникайте глибоких ланцюгів викликів
  • Комбінуйте з event-driven для кращої архітектури

Request/Response — не застарілий підхід. Він просто потребує розумного використання.

Готові побудувати надійну взаємодію між сервісами?

Ми проектуємо та реалізуємо взаємодію мікросервісів на Java (Spring Boot) та JavaScript (Node.js, React). Чи це синхронні API, чи асинхронні події — ми обираємо те, що працює.