Введение: почему вашему проекту нужен API Gateway?
Представьте, что вы архитектор, проектирующий современное здание. Вместо того чтобы прокладывать сотню отдельных дверей для каждой комнаты, вы делаете один центральный вход с ресепшеном, охраной и навигацией. Именно так работает API Gateway для Java сервисов — единая точка входа в вашу микросервисную архитектуру.
Когда я начинал работать с микросервисами на Java, первое, с чем столкнулся — хаос. Клиенты стучались напрямую в десятки сервисов, каждый со своим портом, авторизацией и форматом ошибок. Это было похоже на попытку управлять оркестром, где каждый музыкант играет свою партию, не слушая дирижера. Решение пришло именно в виде API шлюза Java.
В этой статье мы не просто поговорим о теории. Мы разберем живые примеры, напишем код на Java с использованием Spring Cloud Gateway, и вы сможете сразу применить эти знания в своем проекте. Готовы превратить хаос в порядок? Поехали.
Что такое API Gateway и зачем он нужен?
API Gateway (шлюз API) — это промежуточный слой между клиентами (веб-приложения, мобильные приложения, внешние сервисы) и вашими внутренними микросервисами. Он берет на себя всю "грязную работу": маршрутизацию, аутентификацию, балансировку, кэширование и мониторинг.
В экосистеме Java для этого чаще всего используют Spring Cloud Gateway — реактивный шлюз на основе Spring WebFlux, который работает невероятно быстро и гибко.
Основные задачи API Gateway в Java микросервисах:
- Единая точка входа — все запросы идут через один хост:port
- Маршрутизация — перенаправление запросов к нужным сервисам
- Балансировка нагрузки — распределение трафика между инстансами
- Безопасность — проверка JWT токенов, API ключей
- Агрегация ответов — объединение данных из нескольких сервисов
- Rate limiting — ограничение частоты запросов
Без API Gateway ваша архитектура напоминает спагетти-код: каждый клиент знает про каждый сервис. С ним — вы получаете чистую, управляемую систему.
Создаем API Gateway на Java с Spring Cloud Gateway
Давайте перейдем от теории к практике. Я покажу, как собрать рабочий API Gateway для Java сервисов буквально за 15 минут.
Шаг 1: Зависимости и настройка проекта
Создайте новый проект Spring Boot (рекомендую версию 3.x) и добавьте в pom.xml следующие зависимости:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- Для регистрации в Service Discovery (опционально) -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
Не забудьте добавить BOM для Spring Cloud в <dependencyManagement>:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2023.0.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Шаг 2: Конфигурация маршрутов через YAML
Самый простой способ настроить маршрутизацию запросов Java — через application.yml. Вот пример, который перенаправляет запросы к сервисам пользователей и заказов:
spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://user-service
predicates:
- Path=/api/users/**
filters:
- StripPrefix=1
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
- id: order-service
uri: lb://order-service
predicates:
- Path=/api/orders/**
filters:
- StripPrefix=1
- AddRequestHeader=X-Gateway-Version, 1.0
Что здесь происходит?
lb://— указывает на балансировку нагрузки через Service Discovery (Eureka)StripPrefix=1— убирает первый сегмент пути (/api) перед отправкой в микросервисRequestRateLimiter— ограничивает количество запросов (требует Redis)
Шаг 3: Программная настройка маршрутов (Java Config)
Иногда YAML недостаточно гибок. Например, нужно динамически менять маршруты или добавлять сложную логику. Для этого используем Java-конфигурацию:
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class GatewayConfig {
@Bean
public RouteLocator customRoutes(RouteLocatorBuilder builder) {
return builder.routes()
.route("user-service", r -> r
.path("/api/users/**")
.filters(f -> f
.stripPrefix(1)
.addRequestHeader("X-Gateway", "true")
.circuitBreaker(config -> config
.setName("userServiceCB")
.setFallbackUri("forward:/fallback/users")))
.uri("lb://user-service"))
.route("order-service", r -> r
.path("/api/orders/**")
.and().method("GET", "POST") // только GET и POST
.filters(f -> f
.stripPrefix(1)
.retry(3)) // автоматический повтор при ошибках
.uri("lb://order-service"))
.build();
}
}
Обратите внимание: мы добавили Circuit Breaker (предохранитель) для user-service. Если сервис падает, шлюз перенаправит запрос на fallback-эндпоинт. Это критически важно для надежности Java микросервисов.
Безопасность API Gateway: JWT и фильтры
API шлюз Java — идеальное место для централизованной проверки безопасности. Вместо того чтобы дублировать логику аутентификации в каждом сервисе, делаем это один раз.
Реализуем глобальный фильтр, который проверяет JWT токен:
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server