JavaRush /Курсы /Модуль 5. Spring /Лекция 280: Тестирование и деплой микросервисов

Лекция 280: Тестирование и деплой микросервисов

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

Итак, друзья! Мы с вами практически на финишной прямой нашего курса. Сегодня мы будем говорить о том, как довести наше микросервисное приложение от состояния "оно вроде работает на моём компьютере" до "оно стабильно работает в продакшене и всё покрыто тестами". Почему это важно? Потому что мир технологий жесток: если ваш сервис упадёт в 3 часа ночи, вы, а не ваши пользователи, будете проклинать тот день, когда забыли протестировать и задеплоить всё как следует.


Процессы тестирования

Интеграционные тесты: проверяем связность сервисов

Интеграционные тесты позволяют убедиться, что отдельные компоненты системы (например, микросервисы) корректно взаимодействуют друг с другом. Мы не тестируем каждую деталь, но проверяем "магистральное движение данных" между сервисами.

Пример: протестируем REST API одного из наших микросервисов с использованием Spring Boot Test и MockMvc:


@SpringBootTest
@AutoConfigureMockMvc
public class UserServiceIntegrationTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void testGetUserById() throws Exception {
        mockMvc.perform(get("/users/1"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.id").value(1))
                .andExpect(jsonPath("$.name").value("John Doe"));
    }
}

Этот код создаёт тестовый контекст Spring и отправляет HTTP-запрос к эндпоинту нашего микросервиса. Если бы что-то пошло не так, например, микросервис не смог бы достать данные из базы, тест бы провалился.

Нагрузочные тесты: насколько это всё быстро?

Нагрузочные тесты помогают оценить, как ваша система ведёт себя под высоким трафиком. Например, вы можете использовать Apache JMeter или Gatling для симуляции запросов. Настройте сценарий, где 1000 пользователей одновременно отправляют запросы к API, и смотрите, где "узкие места".

Контрактное тестирование: всё ли микросервисы понимают друг о друге?

Когда ваши микросервисы общаются, важно, чтобы они договаривались о формате данных. Здесь на помощь приходит Pact. Этот инструмент позволяет протестировать взаимодействие, чтобы изменения в одном сервисе не ломали другой.

Пример использования Pact для продюсера:


@ExtendWith(PactConsumerTestExt.class)
class ConsumerPactTest {

    @Pact(consumer = "UserConsumer", provider = "UserProvider")
    public RequestResponsePact createPact(PactDslWithProvider builder) {
        return builder
                .given("User exists")
                .uponReceiving("Request for user")
                .path("/users/1")
                .method("GET")
                .willRespondWith()
                .status(200)
                .body("{ \"id\": 1, \"name\": \"John Doe\" }")
                .toPact();
    }

    @Test
    @PactTestFor(pactMethod = "createPact")
    public void testPact(MockServer mockServer) {
        String url = mockServer.getUrl() + "/users/1";
        RestTemplate restTemplate = new RestTemplate();
        String response = restTemplate.getForObject(url, String.class);
        Assertions.assertEquals("{\"id\":1,\"name\":\"John Doe\"}", response);
    }
}

Здесь мы говорим "если провайдер отправляет такой JSON, я гарантирую, что мой консъюмер это съест".

Тестирование асинхронности: обработка Kafka-сообщений

Когда у вас есть Kafka, то без тестов для продюсеров и консъюмеров не обойтись. Для этого можно использовать библиотеку Embedded Kafka, которая поднимает тестовый кластер прямо внутри вашего Java-приложения.

Пример теста консюмера:


@SpringBootTest
@EnableKafka
@EmbeddedKafka(partitions = 1, topics = "test-topic")
public class KafkaConsumerTest {

    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;

    @Test
    public void testKafkaConsumer() {
        String message = "Hello Kafka!";
        kafkaTemplate.send("test-topic", message);

        // Подождём чуть-чуть, чтобы консъюмер получил сообщение
        Awaitility.await()
                .atMost(5, TimeUnit.SECONDS)
                .untilAsserted(() -> {
                    // Проверяем, что сообщение обработано
                    assertTrue(myCustomCondition());
                });
    }
}

Подготовка к деплою

CI/CD пайплайн: автоматизация сборки и тестирования

После того как мы протестировали всё возможное, нужно подготовить автоматический процесс сборки и развертывания. Это поможет избежать ситуации, когда "тесты на локальном компьютере прошли, а на сервере всё упало".

Пример простого GitLab CI пайплайна


stages:
  - build
  - test
  - deploy

build:
  stage: build
  script:
    - ./gradlew build
  artifacts:
    paths:
      - build/libs/*.jar

test:
  stage: test
  script:
    - ./gradlew test

deploy:
  stage: deploy
  script:
    - docker-compose up -d
    only:
      - main

Этот пайплайн:

  1. Сначала собирает наш Spring Boot проект в JAR-файл.
  2. Запускает тесты для проверки работоспособности.
  3. Разворачивает приложение в Docker.

Контейнеризация: Docker

Теперь, чтобы деплой был простым, каждое приложение будет упаковано в Docker-контейнер.

Dockerfile для микросервиса


FROM openjdk:17-jdk-slim
COPY build/libs/my-microservice.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]

Docker-compose для развёртывания нескольких микросервисов


version: "3.8"
services:
  user-service:
    build:
      context: ./user-service
    ports:
      - "8081:8080"

  order-service:
    build:
      context: ./order-service
    ports:
      - "8082:8080"

  kafka:
    image: bitnami/kafka:latest
    ports:
      - "9092:9092"

Эта конфигурация поднимет два микросервиса и Kafka.


Деплой и мониторинг

Деплой в тестовое окружение

Перед продакшеном система должна пройти тесты в тестовом окружении. Убедитесь, что:

  • Все микросервисы поднялись.
  • Kafka принимает и обрабатывает сообщения.
  • API Gateway маршрутизирует запросы правильно.

Мониторинг в продакшене

Настройте Spring Boot Actuator и подключите метрики к инструментам мониторинга, таким как Prometheus и Grafana. Пример настройки метрик:

application.yml


management:
  endpoints:
    web:
      exposure:
        include: "*"

Подключите Actuator к Prometheus, и вы сможете отслеживать нагрузку и состояние микросервисов на дашбордах Grafana.


Таким образом, мы протестировали наши микросервисы, автоматизировали их сборку и реализовали развёртывание с использованием современных CI/CD практик. Теперь наша система готова к бою!

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