Какие знаешь три шаблона проектирования связанных с микросервисом?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Три шаблона проектирования для микросервисов
В архитектуре микросервисов выделяют несколько критических паттернов, которые решают специфические проблемы распределённых систем.
1. Service Discovery (Обнаружение сервисов)
Проблема: В микросервисной архитектуре сервисы динамически разворачиваются и удаляются. Как компоненты узнают, где находятся друг друга в сети?
Решение: Service Discovery автоматически регистрирует сервисы в центральном реестре и позволяет клиентам находить их.
// Пример с Eureka (Spring Cloud)
@SpringBootApplication
@EnableEurekaServer
public class ServiceRegistryApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceRegistryApplication.class, args);
}
}
// Регистрация сервиса
@SpringBootApplication
@EnableEurekaClient
@RestController
public class UserServiceApplication {
@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id) {
return new User(id, "John");
}
}
// Использование через RestTemplate
@Service
public class OrderService {
@Autowired
private RestTemplate restTemplate;
public User getUserInfo(Long userId) {
// URL получается автоматически из Service Discovery
return restTemplate.getForObject(
"http://user-service/users/" + userId,
User.class
);
}
}
Существует две разновидности:
- Client-side discovery: Клиент сам запрашивает реестр и выбирает сервис (Netflix Eureka)
- Server-side discovery: Load balancer / API Gateway автоматически маршрутизирует запросы
2. Circuit Breaker (Автоматический выключатель)
Проблема: Если один микросервис отказал, он может привести к каскадному отказу всей системы. Сервис A вызывает B, B вызывает C... и все зависают в ожидании.
Решение: Circuit Breaker немедленно прерывает запросы к отказавшему сервису, не тратя время на ожидание.
// Пример с Resilience4j
@Service
public class PaymentService {
private final CircuitBreaker circuitBreaker;
private final RestTemplate restTemplate;
public PaymentService(CircuitBreakerRegistry registry) {
this.circuitBreaker = registry.circuitBreaker("payment-service");
}
// States: CLOSED (нормально) -> OPEN (отказ) -> HALF_OPEN (проверка) -> CLOSED
@CircuitBreaker(name = "payment-service")
@Retry(name = "payment-service")
@Fallback(fallback = "paymentFallback")
public PaymentResponse processPayment(Long orderId) {
return restTemplate.postForObject(
"http://payment-service/process",
new PaymentRequest(orderId),
PaymentResponse.class
);
}
// Fallback метод, вызывается если circuit открыт
public PaymentResponse paymentFallback(Long orderId, Exception ex) {
log.error("Payment service failed", ex);
return new PaymentResponse(
orderId,
"PENDING", // Повторим позже
ex.getMessage()
);
}
}
// Конфигурация
@Configuration
public class CircuitBreakerConfig {
@Bean
public CircuitBreaker circuitBreaker(CircuitBreakerRegistry registry) {
CircuitBreakerConfig config = CircuitBreakerConfig.custom()
.failureRateThreshold(50) // 50% ошибок - открываем
.slowCallRateThreshold(50) // 50% slow calls
.slowCallDurationThreshold(Duration.ofSeconds(2))
.waitDurationInOpenState(Duration.ofSeconds(10))
.build();
return registry.circuitBreaker("payment-service", config);
}
}
Три состояния:
- CLOSED: Все работает нормально, запросы проходят
- OPEN: Детектировано много ошибок, запросы отказываются сразу (fail-fast)
- HALF_OPEN: После перерыва пытаемся восстановление, пропускаем один запрос
3. API Gateway (API шлюз)
Проблема: Клиент должен знать адреса всех микросервисов. Если переместить сервис, все клиенты ломаются. Также нужна централизованная аутентификация, логирование, rate limiting.
Решение: Единая точка входа, которая маршрутизирует запросы к нужным сервисам и применяет cross-cutting concerns.
// Spring Cloud Gateway пример
@SpringBootApplication
public class ApiGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(ApiGatewayApplication.class, args);
}
}
// Конфигурация маршрутов
@Configuration
public class GatewayRouteConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
// Маршрут к User Service
.route("users", r -> r
.path("/api/users/**")
.filters(f -> f
.stripPrefix(1)
.addRequestHeader("X-User-Id", "123")
.circuitBreaker(config -> config
.setName("user-service-cb")
.setFallbackUri("forward:/fallback")
)
)
.uri("lb://user-service") // Load balanced
)
// Маршрут к Order Service
.route("orders", r -> r
.path("/api/orders/**")
.filters(f -> f
.stripPrefix(1)
.authenticate() // Custom filter
.rateLimit(config -> config.setCapacity(100))
)
.uri("lb://order-service")
)
.build();
}
}
// Custom фильтр для аутентификации
@Component
public class AuthenticationFilter implements GlobalFilter {
@Override
public Mono<Void> filter(
ServerWebExchange exchange,
GatewayFilterChain chain) {
String token = exchange.getRequest()
.getHeaders()
.getFirst("Authorization");
if (token == null || !validateToken(token)) {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().writeWith(
Mono.just(exchange.getResponse()
.bufferFactory()
.wrap("Unauthorized".getBytes()))
);
}
return chain.filter(exchange);
}
}
Функции API Gateway:
- Маршрутизация запросов к правильным сервисам
- Балансировка нагрузки
- Аутентификация и авторизация
- Rate limiting и throttling
- Request/response трансформация
- Логирование и мониторинг
Как эти паттерны работают вместе
- Service Discovery помогает Gateway узнать, где находятся сервисы
- API Gateway использует Service Discovery для маршрутизации
- Circuit Breaker защищает от каскадных отказов при вызовах между сервисами через Gateway
Вместе они образуют надёжную, масштабируемую архитектуру микросервисов.