JavaRush /Курси /Модуль 5. Spring /Лекція 168: Підходи до комунікації між мікросервісами: си...

Лекція 168: Підходи до комунікації між мікросервісами: синхронна (REST) і асинхронна (повідомлення)

Модуль 5. Spring
Рівень 11 , Лекція 7
Відкрита

Пора поговорити про те, як ці автономні вчені-мікросервіси все ж таки «спілкуються» один з одним. І тут, як у житті, є два популярні способи: говорити напряму (синхронно) або надсилати листи/повідомлення (асинхронно).

Уяви собі звичайний робочий процес в офісі. Коли тобі терміново потрібна інформація від колеги, ти підходиш до нього напряму або дзвониш (синхронна комунікація). Коли завдання не горить, ти надсилаєш email і спокійно займаєшся іншими справами, поки чекаєш відповідь (асинхронна комунікація). Вибір способу спілкування залежить від терміновості й важливості питання.

Так само й мікросервіси можуть спілкуватися різними способами в залежності від їх завдань. Наприклад:

  • Якщо мікросервісу A потрібна негайна відповідь від мікросервісу B, він звертається до нього напряму через REST API.
  • Якщо мікросервісу A неважлива терміновість відповіді, він відправить повідомлення через брокера (наприклад, Kafka).

Отже, синхронна чи асинхронна комунікації — це два фундаментальні підходи, які забезпечують взаємодію між сервісами в мікросервісній архітектурі.

Синхронна комунікація через REST API

Синхронна комунікація означає, що сервіс робить запит і чекає відповіді від іншого сервісу. Це схоже на телефонний дзвінок: ти дзвониш другу і чекаєш, поки він відповість. Якщо він не відповідає, дзвониш знову або кидаєш слухавку.

У світі мікросервісів найпопулярнішим способом синхронної комунікації є REST API.

Приклад синхронної взаємодії з REST

Припустимо, ти розробляєш систему замовлення їжі. У тебе є два мікросервіси:

  1. OrderService — відповідає за обробку замовлень.
  2. PaymentService — відповідає за обробку платежів.

Сценарій: при оформленні клієнтом замовлення OrderService повинен викликати PaymentService, щоб перевірити, чи достатньо коштів для оплати. Ось як це може виглядати:


// OrderService: Виклик REST API PaymentService (синхронний запит)
@RestController
@RequestMapping("/orders")
public class OrderController {

    @PostMapping
    public ResponseEntity<String> createOrder(@RequestBody OrderRequest orderRequest) {
        // Логіка створення замовлення

        // Надсилаємо запит в PaymentService
        RestTemplate restTemplate = new RestTemplate();
        String paymentUrl = "http://localhost:8081/payment/validate";
        PaymentResponse paymentResponse = restTemplate.postForObject(paymentUrl, orderRequest, PaymentResponse.class);

        if (paymentResponse.isPaymentValid()) {
            return ResponseEntity.ok("Order created successfully.");
        } else {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Payment failed.");
        }
    }
}

Переваги синхронної комунікації

  • Проста реалізація: REST API — це стандарт, який багато розробників вже розуміють, а інструменти (наприклад, Spring RestTemplate і WebClient) суттєво спрощують роботу.
  • Прямий доступ: сервіс викликає інший сервіс напряму, отримує відповідь одразу.
  • Звичність: REST API широко застосовується і зрозумілий як розробникам, так і менеджерам.

Обмеження синхронної комунікації

  • Часова залежність: якщо PaymentService недоступний, то OrderService також «зависає», що може порушити роботу всієї системи.
  • Проблеми з масштабуванням: якщо навантаження на OrderService збільшиться, PaymentService також має справлятися з великою кількістю запитів.
  • Підвищена затримка: кожен виклик REST — це час очікування, що може уповільнити загальну продуктивність.

Коли використовувати синхронну комунікацію?

  • Коли потрібна миттєва відповідь.
  • Коли залежність між сервісами тісна (наприклад, перевірка платіжних даних).
  • Коли відмови в одному сервісі критично впливають на інший.

Асинхронна комунікація з використанням повідомлень

Асинхронність передбачає, що один сервіс відправляє повідомлення іншому через брокера (наприклад, Kafka, RabbitMQ або ActiveMQ) і не чекає негайної відповіді. Це більше схоже на відправку електронного листа: ти написав повідомлення і продовжив займатися своїми справами, а отримувач відповість, коли зможе.

Основні концепції асинхронної комунікації

  • Брокери повідомлень (Message Brokers): зазвичай використовується посередник, наприклад, Kafka, який зберігає і доставляє повідомлення.
  • Продюсер і Консьюмер: сервіс-відправник називається продюсером (producer), а сервіс-одержувач — консьюмером (consumer).
  • Топіки: повідомлення відправляються в "топіки" (topics), які діють як поштові скриньки.

Приклад асинхронної взаємодії через Kafka

Продовжимо приклад з OrderService і PaymentService. Припустимо, ми хочемо відправити замовлення на оплату асинхронно.

Публікуємо повідомлення (Продюсер):


// OrderService: Відправка повідомлення в Kafka
@RestController
@RequestMapping("/orders")
public class OrderController {

    private final KafkaTemplate<String, OrderRequest> kafkaTemplate;

    public OrderController(KafkaTemplate<String, OrderRequest> kafkaTemplate) {
        this.kafkaTemplate = kafkaTemplate;
    }

    @PostMapping
    public ResponseEntity<String> createOrder(@RequestBody OrderRequest orderRequest) {
        kafkaTemplate.send("payment-topic", orderRequest); // Надсилаємо повідомлення
        return ResponseEntity.ok("Order created successfully. Payment will be processed.");
    }
}

Обробляємо повідомлення (Консьюмер):


// PaymentService: Отримання повідомлення з Kafka
@Component
public class PaymentConsumer {

    @KafkaListener(topics = "payment-topic", groupId = "payment-group")
    public void handlePayment(OrderRequest orderRequest) {
        // Логіка обробки платежу
        System.out.println("Processing payment for order: " + orderRequest.getOrderId());
    }
}

Переваги асинхронної комунікації

  • Зменшення залежності: сервіси працюють незалежно один від одного. Навіть якщо PaymentService вимкнений, OrderService продовжить працювати.
  • Підвищена масштабованість: брокери повідомлень, такі як Kafka, можуть обробляти величезні обсяги даних.
  • Гнучкість взаємодії: кілька консьюмерів можуть підписатися на один топік, що зручно для складних систем.

Обмеження асинхронної комунікації

  • Складність реалізації: потрібна настройка брокера повідомлень і обробка помилок (наприклад, недоставлених повідомлень).
  • Відсутність негайної відповіді: якщо успішність операції критична, це може бути проблемою.
  • Гарантії доставки: не всі брокери повідомлень підтримують сувору гарантію доставки.

Коли використовувати асинхронну комунікацію?

  • Коли задача не потребує негайного завершення (наприклад, відправка сповіщень).
  • Коли потрібно роз’єднати сервіси і зменшити їх взаємозалежність.
  • Коли потрібно ефективно обробляти великий обсяг даних.

Вибір між синхронною і асинхронною комунікацією

Вибір підходу залежить від конкретного сценарію. Ось кілька рекомендацій:

Критерій Синхронна (REST) Асинхронна (Повідомлення)
Негайність відповіді Потрібна Не потрібна
Залежність між сервісами Висока Низька
Обсяг даних Невеликий Великий
Масштабованість Обмежена Висока
Складність реалізації Низька Висока

Типові помилки при використанні підходів

  • Використання REST для задач, які не потребують негайної відповіді, веде до збільшення затримок і залежностей.
  • Ігнорування обробки помилок в асинхронній комунікації може призвести до втрати повідомлень.
  • Неправильне проектування топіків Kafka (наприклад, занадто багато продюсерів і консьюмерів на одному топіку) створює хаос.

Щоб уникнути цих проблем, ретельно аналізуйте вимоги системи і обирайте підхід, який найкраще відповідає вашим цілям.


На цьому етапі ми вже розібралися, як мікросервіси можуть взаємодіяти один з одним за допомогою синхронного REST і асинхронних повідомлень. У наступній лекції ми почнемо заглиблюватися в декомпозицію додатків для мікросервісної архітектури. Побачимось у коді! 😉

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ