JavaRush /Курсы /Модуль 5. Spring /Лекция 274: Реализация микросервисов для обработки событи...

Лекция 274: Реализация микросервисов для обработки событий

Модуль 5. Spring
28 уровень , 3 лекция
Открыта

Теперь мы находимся на этапе реализации микросервисов для обработки событий — того самого момента, когда магия становится реальностью (или, по крайней мере, стремится ею стать). Сегодня мы будем создавать небольшую, но функциональную систему обработки событий с использованием Spring Boot и Kafka. Готовы к кодингу? Тогда пристегнитесь: этот путь будет увлекательным.


Зачем нужны события и как они помогают микросервисам

Микросервисы, как и коллега в соседнем кубикле, должны взаимодействовать друг с другом. Вместо того чтобы напрямую обращаться к другому сервису (что бы создало излишнюю связанность), микросервисы используют события. Например, когда пользователь оформляет заказ в интернет-магазине, событие OrderCreated может быть отправлено в топик Kafka, чтобы другие микросервисы (например, склад, доставка и оплаты) могли обработать его.

Вот что делают события:

  • Разрывают связь между сервисами: чтобы один сервис не "знал" слишком много про другой.
  • Обеспечивают асинхронную обработку: ваш сервис не будет простаивать в ожидании ответа на запрос.
  • Способствуют масштабируемости: количество сообщений можно распределять по нескольким консьюмерам.

Этап 1: Создание микросервиса

Начнем с создания простого микросервиса, который будет отправлять события в Kafka — это будет наш Order Service. Этот сервис будет принимать запросы на создание заказа и публиковать событие OrderCreated.

Шаг 1: Настройка проекта в Spring Boot

Создаём новый Spring Boot проект с такими зависимостями:

  • Spring Web (для REST API)
  • Spring Kafka (для интеграции с Kafka)
  • Spring Boot Actuator (для мониторинга)
  • Spring Boot DevTools (для упрощения разработки, необязательная опция)

Если используете Maven, добавьте вот такие зависимости в pom.xml:


<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.kafka</groupId>
        <artifactId>spring-kafka</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
</dependencies>

Если у вас Gradle (привет, любители лаконичности YAML), используйте это:


dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.kafka:spring-kafka'
    implementation 'org.springframework.boot:spring-boot-starter-actuator'
}

Шаг 2: Конфигурация Kafka

Добавьте в application.yml конфигурацию для Kafka:


spring:
  kafka:
    bootstrap-servers: localhost:9092
    producer:
      key-serializer: org.apache.kafka.common.serialization.StringSerializer
      value-serializer: org.apache.kafka.common.serialization.StringSerializer
    consumer:
      key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
      value-deserializer: org.apache.kafka.common.serialization.StringDeserializer

Эта конфигурация указывает, где находится Kafka, и какие сериализаторы/десериализаторы использовать. Если вы ещё не настроили Kafka, вернитесь к лекции 185 для подробностей!

Шаг 3: Создание продюсера (отправка сообщений)

Создайте класс OrderProducer, который будет отправлять сообщения в Kafka:


import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;

@Service
public class OrderProducer {

    private final KafkaTemplate<String, String> kafkaTemplate;

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

    public void sendOrderCreatedEvent(String orderId) {
        kafkaTemplate.send("order-events", orderId);
        System.out.println("Отправлено событие для заказа: " + orderId);
    }
}

Здесь мы используем KafkaTemplate, который является частью Spring Kafka, для отправки сообщений в топик order-events.

Шаг 4: Создание REST-контроллера

Теперь добавьте REST-контроллер для обработки запросов на создание заказов:


import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/orders")
public class OrderController {

    private final OrderProducer orderProducer;

    public OrderController(OrderProducer orderProducer) {
        this.orderProducer = orderProducer;
    }

    @PostMapping("/{orderId}")
    public String createOrder(@PathVariable String orderId) {
        orderProducer.sendOrderCreatedEvent(orderId);
        return "Заказ создан: " + orderId;
    }
}

Этот контроллер принимает POST запросы для создания заказов и публикует событие через продюсер.

Проверка

Запустите ваше приложение и отправьте POST запрос через Postman или CURL:


curl -X POST http://localhost:8080/orders/12345

Если вы видите в логах Отправлено событие для заказа: 12345, значит, всё работает. Осталось обработать это событие на другой стороне.


Этап 2: Обработка событий в другом микросервисе

Теперь создадим другой микросервис, который будет слушать топик order-events. Этот сервис, скажем, будет называться Inventory Service и обновит остатки на складе для созданного заказа.

Шаг 1: Настройка консьюмера

В Inventory Service добавьте зависимость spring-kafka точно так же, как мы сделали это в Order Service. Добавьте следующую конфигурацию в application.yml:


spring:
  kafka:
    bootstrap-servers: localhost:9092
    consumer:
      group-id: inventory-service
      auto-offset-reset: earliest
      key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
      value-deserializer: org.apache.kafka.common.serialization.StringDeserializer

Шаг 2: Создание консьюмера

Создайте класс OrderConsumer, который будет слушать сообщения:


import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Service;

@Service
public class OrderConsumer {

    @KafkaListener(topics = "order-events", groupId = "inventory-service")
    public void processOrderCreatedEvent(String orderId) {
        System.out.println("Получено событие для заказа: " + orderId);
        // Здесь добавьте бизнес-логику, например, обновление остатков
    }
}

Аннотация @KafkaListener указывает, что этот метод будет вызван для каждого сообщения из топика order-events.

Проверка

Запустите сначала Kafka, затем оба микросервиса. После этого отправьте POST запрос снова. Вы должны увидеть в логах Inventory Service сообщение: Получено событие для заказа: 12345.


Этап 3: Обеспечение целостности

Когда мы говорим о событиях, важно понимать, что сообщения могут теряться или дублироваться. Чтобы этого не происходило:

  1. Убедитесь, что ваш Kafka топик настроен с "At least once" гарантией.
  2. Реализуйте логику идемпотентности в потребителе. Например, храните обработанные события в базе данных, чтобы не обрабатывать их дважды.

Теперь у вас есть рабочая система с двумя микросервисами, которые обмениваются событиями через Kafka. Это базис для событийно-ориентированных архитектур! В следующей лекции мы продолжим наши приключения, добавив дополнительные компоненты для мониторинга и логирования.

Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ