← Назад к вопросам

Какие знаешь три шаблона проектирования связанных с микросервисом?

1.8 Middle🔥 171 комментариев
#SOLID и паттерны проектирования

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Три шаблона проектирования для микросервисов

В архитектуре микросервисов выделяют несколько критических паттернов, которые решают специфические проблемы распределённых систем.

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 трансформация
  • Логирование и мониторинг

Как эти паттерны работают вместе

  1. Service Discovery помогает Gateway узнать, где находятся сервисы
  2. API Gateway использует Service Discovery для маршрутизации
  3. Circuit Breaker защищает от каскадных отказов при вызовах между сервисами через Gateway

Вместе они образуют надёжную, масштабируемую архитектуру микросервисов.

Какие знаешь три шаблона проектирования связанных с микросервисом? | PrepBro