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

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

3.0 Senior🔥 181 комментариев
#REST API и микросервисы#SOLID и паттерны проектирования

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

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

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

Шаблоны проектирования микросервисной архитектуры

Микросервисная архитектура — это новая парадигма, которую я активно применяю в своих проектах. Существует множество проверенных паттернов, которые помогают избежать типичных ошибок.

1. Service Discovery

Микросервисы должны динамически обнаруживать друг друга без жёсткого конфигурирования IP адресов.

Реализация с Eureka (Spring Cloud):

@SpringBootApplication
@EnableEurekaServer
public class ServiceDiscoveryApplication {
    public static void main(String[] args) {
        SpringApplication.run(ServiceDiscoveryApplication.class, args);
    }
}

// В микросервисе
@SpringBootApplication
@EnableEurekaClient
public class UserServiceApplication {
    @LoadBalanced
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

@Service
public class OrderService {
    private final RestTemplate restTemplate;
    
    public void createOrder(Order order) {
        // Eureka автоматически разрешает адрес
        restTemplate.postForObject(
            "http://user-service/api/v1/users/validate",
            order.getUserId(),
            User.class
        );
    }
}

2. API Gateway

API Gateway — это единая точка входа для всех запросов клиентов. Маршрутизирует их к нужным микросервисам.

# application.yml
spring:
  cloud:
    gateway:
      routes:
        - id: user-service
          uri: lb://user-service
          predicates:
            - Path=/api/v1/users/**
        - id: order-service
          uri: lb://order-service
          predicates:
            - Path=/api/v1/orders/**
@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 || !isValidToken(token)) {
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        
        return chain.filter(exchange);
    }
}

3. Circuit Breaker

Если один микросервис падает, остальная система должна продолжать работать.

@Service
public class PaymentService {
    
    @CircuitBreaker(name = "paymentBreaker", fallbackMethod = "fallbackPayment")
    public void processPayment(Order order) {
        // Вызов внешнего сервиса
        paymentGateway.charge(order.getAmount());
    }
    
    public void fallbackPayment(Order order, Exception e) {
        // Откладываем платёж в очередь для обработки позже
        paymentQueue.enqueue(order);
        logger.warn("Payment gateway unavailable, queued order: {}", order.getId());
    }
}

// application.yml конфигурация
resilience4j:
  circuitbreaker:
    instances:
      paymentBreaker:
        registerHealthIndicator: true
        slidingWindowSize: 10
        failureRateThreshold: 50
        waitDurationInOpenState: 5000

4. Saga Pattern для распределённых транзакций

Разных сервисов не могут работать в одной ACID транзакции. Используем Saga:

// Choreography-based Saga
@Service
public class OrderService {
    private final ApplicationEventPublisher publisher;
    
    @Transactional
    public void createOrder(Order order) {
        Order savedOrder = orderRepository.save(order);
        
        // Публикуем событие
        publisher.publishEvent(new OrderCreatedEvent(savedOrder));
    }
}

@Service
public class InventoryService {
    
    @EventListener
    @Transactional
    public void handleOrderCreated(OrderCreatedEvent event) {
        Order order = event.getOrder();
        
        try {
            // Резервируем товар
            inventory.reserve(order.getItems());
            publisher.publishEvent(new InventoryReservedEvent(order));
        } catch (InsufficientInventoryException e) {
            // Компенсирующая транзакция
            publisher.publishEvent(new OrderCancelledEvent(order));
        }
    }
}

5. Event-Driven Architecture

Микросервисы общаются через события, а не прямыми вызовами.

@Configuration
public class EventConfig {
    
    @Bean
    public NewTopic userCreatedTopic() {
        return TopicBuilder.name("user-events")
            .partitions(3)
            .replicas(2)
            .build();
    }
}

@Service
public class UserEventPublisher {
    private final KafkaTemplate<String, UserEvent> kafkaTemplate;
    
    public void publishUserCreated(User user) {
        kafkaTemplate.send("user-events", 
            user.getId().toString(),
            new UserCreatedEvent(user));
    }
}

@Service
public class NotificationService {
    
    @KafkaListener(topics = "user-events", groupId = "notification-group")
    public void onUserCreated(UserCreatedEvent event) {
        // Отправляем приветственное письмо
        emailService.sendWelcomeEmail(event.getUser());
    }
}

6. Distributed Tracing

Для отладки запросов, проходящих через несколько сервисов, используем трейсинг:

@Configuration
public class TracingConfig {
    @Bean
    public Sampler defaultSampler() {
        return Sampler.ALWAYS_SAMPLE;
    }
}

@Service
public class OrderService {
    private final Tracer tracer;
    
    public void processOrder(Order order) {
        Span span = tracer.startSpan("process-order");
        try (SpanInScope ignored = tracer.withSpanInScope(span)) {
            span.tag("order.id", order.getId().toString());
            span.tag("order.amount", order.getAmount().toString());
            
            // Обработка
        } finally {
            span.finish();
        }
    }
}

7. Strangler Fig Pattern

Миграция от монолита к микросервисам делается постепенно:

// API Gateway перенаправляет запросы либо на микросервис, либо на старый монолит
@Component
public class LegacyRouterFilter implements GlobalFilter {
    
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        if (isNewFeature(exchange.getRequest().getPath())) {
            // Переходит на новый микросервис
            return chain.filter(exchange);
        } else {
            // Остаётся на старом монолите
            return routeToLegacySystem(exchange);
        }
    }
}

8. CQRS (Command Query Responsibility Segregation)

Разделение логики чтения и записи для оптимизации:

// Command service (запись)
@Service
public class CreateUserCommand {
    private final UserRepository userRepository;
    
    public User execute(CreateUserRequest request) {
        User user = new User(request.getEmail(), request.getName());
        return userRepository.save(user);
    }
}

// Query service (чтение из денормализованного хранилища)
@Service
public class GetUserQuery {
    private final UserReadRepository readRepository;  // MongoDB или Elasticsearch
    
    public UserReadModel execute(UUID userId) {
        return readRepository.findById(userId);
    }
}

9. Service Mesh (Istio, Linkerd)

Делегирует cross-cutting concerns (логирование, авторизация, rate limiting) в инфраструктуру:

# Istio VirtualService
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: order-service
spec:
  hosts:
  - order-service
  http:
  - match:
    - headers:
        user-type:
          exact: premium
    route:
    - destination:
        host: order-service
        subset: v2
      weight: 100
  - route:
    - destination:
        host: order-service
        subset: v1
      weight: 100

Рекомендации по выбору

Начало проекта:

  • Используй API Gateway + Service Discovery
  • Внедри Circuit Breaker рано
  • Логируй всё через централизованное логирование

Масштабирование:

  • Добавь Event-Driven архитектуру
  • Внедри CQRS если есть асимметрия читаемых/записываемых операций
  • Рассмотри Service Mesh при >5 сервисов

Мониторинг:

  • Distributed Tracing обязателен для отладки
  • Используй метрики Prometheus
  • Настрой алерты в Grafana

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