Мы узнали, что такое API Gateway и зачем он нужен в микросервисной архитектуре, как Gateway помогает маршрутизировать запросы, выполнять аутентификацию/авторизацию, балансировать нагрузку и даже защищать систему от атак. еперь пришло время применить теорию на практике и настроить API Gateway, используя Spring Cloud Gateway.
Знаете ли вы, что Netflix был пионером в разработке собственного API Gateway, который вдохновил индустрию? Их проект Zuul настолько успешно справлялся с управлением миллионами запросов в секунду, что Spring Framework разработал Spring Cloud Gateway как современную альтернативу, обладающую более широкой функциональностью.
Что будем делать?
В рамках этой лекции мы настроим Spring Cloud Gateway для маршрутизации запросов между несколькими микросервисами. Вы научитесь не только создавать маршруты, но и использовать фильтры для настройки работы вашего шлюза.
1. Подготовка проекта
Создание нового проекта Spring Boot
Мы начнем с создания нового проекта Spring Boot, который будет выступать в роли API Gateway. Для этого вы можете воспользоваться Spring Initializr или вашим любимым инструментом.
Вот какие модули нам понадобятся:
- Spring Cloud Gateway (обязательно).
- Spring Boot Web Starter (добавляется автоматически).
- Spring Boot Actuator (для мониторинга, опционально).
Настройка pom.xml или build.gradle
Если вы используете Maven, добавьте в ваш pom.xml следующую зависимость:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
Для пользователей Gradle добавьте в build.gradle:
implementation 'org.springframework.cloud:spring-cloud-starter-gateway'
Не забудьте указать правильную версию Spring Cloud в вашем файле конфигурации. Например, если вы используете Spring Boot версии 3.x, то совместимый релиз Spring Cloud будет 2022.x. Укажите это в секции управления версиями.
2. Настройка маршрутов (Routes)
Маршрут (Route) — это базовый строительный блок в Spring Cloud Gateway. Он определяет, куда направить входящий запрос. Начнем с простого примера: перенаправляем все запросы с пути /service1/** на локальный микросервис, запущенный на порту 8081.
Конфигурация в application.yml
Создайте файл application.yml в папке src/main/resources и добавьте минимальную конфигурацию:
spring:
cloud:
gateway:
routes:
- id: service1-route
uri: http://localhost:8081
predicates:
- Path=/service1/**
Что тут происходит:
id: уникальный идентификатор маршрута.uri: куда направлять запросы (наш микросервис на порту8081).predicates: условия, при которых маршрут используется. Здесь мы указали, что запросы, начинающиеся с/service1/, должны обрабатываться этим маршрутом.
Кодовый аналог конфигурации
Если вы не фанат YAML, альтернативой является настройка маршрутов прямо в коде. Вот как это можно реализовать:
@Bean
public RouteLocator customRoutes(RouteLocatorBuilder builder) {
return builder.routes()
.route("service1-route", r -> r.path("/service1/**")
.uri("http://localhost:8081"))
.build();
}
Этот метод возвращает RouteLocator, который содержит все маршруты. Заметьте, что маршруты можно определять более подробно, добавляя фильтры, о чем поговорим ниже.
Тестирование маршрута
Запустите ваш API Gateway и микросервис на порту 8081. Теперь с помощью Postman, curl или браузера выполните запрос:
GET http://localhost:8080/service1/hello
API Gateway перенаправит запрос на микросервис по адресу http://localhost:8081/hello.
3. Использование фильтров
Фильтры позволяют обрабатывать запросы и ответы. Это как вмешательство в "прокси", чтобы добавить или изменить информацию.
Добавление фильтров
Давайте добавим фильтр, который будет добавлять HTTP-заголовок к каждому запросу. Обновим конфигурацию в application.yml:
spring:
cloud:
gateway:
routes:
- id: service1-route
uri: http://localhost:8081
predicates:
- Path=/service1/**
filters:
- AddRequestHeader=X-Custom-Header, HelloWorld
Теперь каждый запрос к /service1/ будет содержать в заголовке X-Custom-Header: HelloWorld.
Реализация кастомного фильтра
Вы также можете реализовать свой собственный фильтр. Например, фильтр, который логирует каждый запрос:
@Component
public class LoggingFilter implements GlobalFilter {
private static final Logger logger = LoggerFactory.getLogger(LoggingFilter.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
logger.info("Request URI: {}", exchange.getRequest().getURI());
return chain.filter(exchange);
}
}
Такой фильтр выполнится для каждого запроса. Если нужен только для определённого маршрута, можно добавить его в цепочку фильтров для конкретного маршрута.
4. Настройка предикатов (Predicates)
Предикаты определяют условия, при которых будет использоваться маршрут. Например, проверим, чтобы запрос обрабатывался только при определенном HTTP-методе.
В application.yml добавьте:
spring:
cloud:
gateway:
routes:
- id: service1-get-route
uri: http://localhost:8081
predicates:
- Path=/service1/**
- Method=GET
Теперь только GET-запросы будут маршрутизироваться. Все остальные методы (POST, PUT и т.д.) будут игнорироваться.
Расширенные предикаты
Вы можете комбинировать предикаты. Например, команда ниже обработает только запросы с GET-методом, которые приходят с хоста mydomain.com:
predicates:
- Path=/service1/**
- Method=GET
- Host=mydomain.com
5. Полезные фильтры и предикаты: Управление CORS
Если ваш API Gateway используется для публичного доступа, нужно учитывать CORS (Cross-Origin Resource Sharing). Добавим следующую настройку:
spring:
cloud:
gateway:
globalcors:
corsConfigurations:
'[/**]':
allowedOrigins: "http://localhost:3000"
allowedMethods:
- GET
- POST
Эта конфигурация разрешает запросы с фронтенда, запущенного на localhost:3000.
6. Проверяем результат
- Убедитесь, что ваши микросервисы работают.
- Откройте Postman или используйте curl для тестирования нескольких маршрутов:
http://localhost:8080/service1/hello— должен перенаправляться на микросервис.http://localhost:8080/service1/unknown— должен возвращать 404, если ресурс не существует в микросервисе.
Если всё работает, то поздравляем! Вы только что создали свой первый API Gateway.
7. Типичные ошибки и их устранение
- Ошибка
404при доступе к маршруту: Проверьте, совпадает ли путь в предикате с отправляемым запросом. - Ошибка
500при вызове микросервиса: Убедитесь, что указанный URI (например,http://localhost:8081) действительно доступен и работает. - CORS-проблемы: Если браузер блокирует запросы, убедитесь, что CORS настроен корректно.
Дальше вы сможете углубляться в более сложные конфигурации API Gateway, добавляя аутентификацию, авторизацию и балансировку нагрузки. Полезные ссылки для изучения:
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ