Сколько микросервисов на проекте?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Микросервисная архитектура: количество сервисов и организация
В моём последнем проекте использовалась микросервисная архитектура с 8 основными микросервисами, плюс несколько вспомогательных сервисов инфраструктуры. Это была сложная и интересная система, которая помогла мне глубоко понять масштабируемость, распределённые системы и операционные вызовы при разработке крупных приложений.
Основные 8 микросервисов
1. User Service (Сервис управления пользователями)
// Порт: 8001
// Ответственность: Регистрация, аутентификация, профили пользователей
@RestController
@RequestMapping("/api/v1/users")
public class UserController {
private final UserService userService;
@PostMapping("/register")
public ResponseEntity<UserDTO> register(@RequestBody RegisterRequest request) {
User user = userService.register(request.getEmail(), request.getPassword());
return ResponseEntity.ok(mapToDTO(user));
}
@PostMapping("/login")
public ResponseEntity<TokenDTO> login(@RequestBody LoginRequest request) {
String token = userService.authenticate(request.getEmail(), request.getPassword());
return ResponseEntity.ok(new TokenDTO(token));
}
@GetMapping("/{id}")
public ResponseEntity<UserDTO> getUser(@PathVariable String id) {
User user = userService.findById(id);
return ResponseEntity.ok(mapToDTO(user));
}
}
2. Product Service (Сервис каталога товаров)
// Порт: 8002
// Ответственность: Управление товарами, категориями, описания
@RestController
@RequestMapping("/api/v1/products")
public class ProductController {
private final ProductService productService;
@GetMapping
public ResponseEntity<Page<ProductDTO>> listProducts(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size) {
Page<Product> products = productService.findAll(page, size);
return ResponseEntity.ok(products.map(this::mapToDTO));
}
@GetMapping("/{id}")
public ResponseEntity<ProductDTO> getProduct(@PathVariable String id) {
Product product = productService.findById(id);
return ResponseEntity.ok(mapToDTO(product));
}
@PostMapping
public ResponseEntity<ProductDTO> createProduct(@RequestBody CreateProductRequest request) {
Product product = productService.create(request);
return ResponseEntity.status(HttpStatus.CREATED).body(mapToDTO(product));
}
}
3. Order Service (Сервис заказов)
// Порт: 8003
// Ответственность: Создание, управление, отслеживание заказов
@RestController
@RequestMapping("/api/v1/orders")
public class OrderController {
private final OrderService orderService;
private final OrderEventPublisher orderEventPublisher;
@PostMapping
public ResponseEntity<OrderDTO> createOrder(@RequestBody CreateOrderRequest request) {
Order order = orderService.create(request);
// Публикуем событие для других сервисов
orderEventPublisher.publishOrderCreated(order);
return ResponseEntity.status(HttpStatus.CREATED).body(mapToDTO(order));
}
@GetMapping("/{id}")
public ResponseEntity<OrderDTO> getOrder(@PathVariable String id) {
Order order = orderService.findById(id);
return ResponseEntity.ok(mapToDTO(order));
}
@PutMapping("/{id}/cancel")
public ResponseEntity<OrderDTO> cancelOrder(@PathVariable String id) {
Order order = orderService.cancel(id);
orderEventPublisher.publishOrderCancelled(order);
return ResponseEntity.ok(mapToDTO(order));
}
}
4. Payment Service (Сервис платежей)
// Порт: 8004
// Ответственность: Обработка платежей, интеграция с платёжными системами
@RestController
@RequestMapping("/api/v1/payments")
public class PaymentController {
private final PaymentService paymentService;
private final ExternalPaymentGateway paymentGateway;
@PostMapping
public ResponseEntity<PaymentDTO> processPayment(@RequestBody ProcessPaymentRequest request) {
// Вызываем внешний шлюз платежей
PaymentResponse response = paymentGateway.charge(
request.getAmount(),
request.getCurrency(),
request.getToken()
);
Payment payment = paymentService.save(response);
return ResponseEntity.ok(mapToDTO(payment));
}
@GetMapping("/{id}")
public ResponseEntity<PaymentDTO> getPayment(@PathVariable String id) {
Payment payment = paymentService.findById(id);
return ResponseEntity.ok(mapToDTO(payment));
}
}
5. Inventory Service (Сервис инвентаря)
// Порт: 8005
// Ответственность: Управление складом, резервирование товаров
@Service
public class InventoryService {
private final InventoryRepository inventoryRepository;
@Transactional
public boolean reserveItems(OrderDTO order) {
for (OrderItem item : order.getItems()) {
Inventory inventory = inventoryRepository.findById(item.getProductId());
if (inventory.getQuantity() < item.getQuantity()) {
return false; // Недостаточно товара
}
inventory.setQuantity(inventory.getQuantity() - item.getQuantity());
inventoryRepository.save(inventory);
}
return true;
}
public void releaseReservation(OrderDTO order) {
// Освобождаем зарезервированные товары
for (OrderItem item : order.getItems()) {
Inventory inventory = inventoryRepository.findById(item.getProductId());
inventory.setQuantity(inventory.getQuantity() + item.getQuantity());
inventoryRepository.save(inventory);
}
}
}
6. Shipping Service (Сервис доставки)
// Порт: 8006
// Ответственность: Управление доставкой, расчёт стоимости, отслеживание
@RestController
@RequestMapping("/api/v1/shipping")
public class ShippingController {
private final ShippingService shippingService;
private final ShippingProvider shippingProvider;
@PostMapping("/calculate")
public ResponseEntity<ShippingQuoteDTO> calculateShipping(
@RequestBody ShippingRequest request) {
ShippingQuote quote = shippingService.calculateCost(
request.getOrigin(),
request.getDestination(),
request.getWeight()
);
return ResponseEntity.ok(mapToDTO(quote));
}
@PostMapping("/{orderId}/create")
public ResponseEntity<TrackingDTO> createShipment(@PathVariable String orderId) {
// Интегрируемся с провайдером доставки
TrackingNumber tracking = shippingProvider.createShipment(orderId);
return ResponseEntity.ok(mapToDTO(tracking));
}
}
7. Notification Service (Сервис уведомлений)
// Порт: 8007
// Ответственность: Email, SMS, push-уведомления
@Service
public class NotificationService {
private final EmailService emailService;
private final SmsService smsService;
private final PushNotificationService pushService;
@Async
public void sendOrderConfirmation(Order order) {
// Email уведомление
EmailMessage email = new EmailMessage();
email.setTo(order.getUser().getEmail());
email.setSubject("Заказ подтверждён");
email.setBody(formatOrderConfirmation(order));
emailService.send(email);
// SMS уведомление
smsService.send(order.getUser().getPhoneNumber(),
"Ваш заказ #" + order.getId() + " подтверждён");
}
@Async
public void sendShippingNotification(String orderId, String trackingNumber) {
Order order = orderService.findById(orderId);
emailService.send(order.getUser().getEmail(),
"Ваша доставка отправлена. Номер отслеживания: " + trackingNumber);
}
}
8. Review Service (Сервис отзывов и рейтингов)
// Порт: 8008
// Ответственность: Отзывы, рейтинги, модерация
@RestController
@RequestMapping("/api/v1/reviews")
public class ReviewController {
private final ReviewService reviewService;
@PostMapping
public ResponseEntity<ReviewDTO> createReview(@RequestBody CreateReviewRequest request) {
Review review = reviewService.create(
request.getProductId(),
request.getUserId(),
request.getRating(),
request.getComment()
);
return ResponseEntity.status(HttpStatus.CREATED).body(mapToDTO(review));
}
@GetMapping("/product/{productId}")
public ResponseEntity<Page<ReviewDTO>> getProductReviews(@PathVariable String productId) {
Page<Review> reviews = reviewService.findByProductId(productId);
return ResponseEntity.ok(reviews.map(this::mapToDTO));
}
}
Архитектура и коммуникация
Диаграмма микросервисов:
API Gateway (8000)
↓
┌───────────────────────────────────────────────┐
│ Микросервисы │
├───────────────────────────────────────────────┤
│ User (8001) Product (8002) Order (8003) │
│ Payment (8004) Inventory (8005) Shipping (8006)│
│ Notification (8007) Review (8008) │
└───────────────────────────────────────────────┘
↓
┌───────────────────────────────────────────────┐
│ Message Broker (RabbitMQ / Kafka) │
│ - Event-driven коммуникация │
│ - Асинхронная обработка │
└───────────────────────────────────────────────┘
Вспомогательные сервисы инфраструктуры
1. API Gateway (Порт 8000)
- Маршрутизация запросов
- Аутентификация
- Rate limiting
- Load balancing
2. Service Discovery (Consul / Eureka)
- Регистрация и обнаружение сервисов
- Health checks
3. Config Server
- Централизованное управление конфигурацией
4. Message Broker (RabbitMQ / Kafka)
- Asynchronous коммуникация между сервисами
- Event streaming
Event-Driven Communication
// Order Service публикует событие
public class OrderService {
@Autowired
private RabbitTemplate rabbitTemplate;
public void createOrder(CreateOrderRequest request) {
Order order = saveOrder(request);
// Публикуем событие
rabbitTemplate.convertAndSend(
"orders.exchange",
"orders.created",
new OrderCreatedEvent(order)
);
}
}
// Inventory Service слушает событие
@Component
public class InventoryEventListener {
@RabbitListener(queues = "inventory.queue")
public void handleOrderCreated(OrderCreatedEvent event) {
inventoryService.reserveItems(event.getOrder());
}
}
// Notification Service слушает событие
@Component
public class NotificationEventListener {
@RabbitListener(queues = "notification.queue")
public void handleOrderCreated(OrderCreatedEvent event) {
notificationService.sendOrderConfirmation(event.getOrder());
}
}
Вызовы микросервисной архитектуры
1. Распределённые транзакции (Saga Pattern)
// Обработка платежа требует координации нескольких сервисов
public class PaymentSaga {
public void executePayment(Order order) {
try {
// Шаг 1: Зарезервировать товары
inventoryService.reserve(order);
// Шаг 2: Обработать платёж
paymentService.charge(order);
// Шаг 3: Создать доставку
shippingService.createShipment(order);
// Шаг 4: Отправить уведомление
notificationService.notify(order);
} catch (Exception e) {
// Компенсирующие транзакции
inventoryService.release(order);
notificationService.notifyError(order);
throw e;
}
}
}
2. Мониторинг и логирование
// Используем ELK Stack (Elasticsearch, Logstash, Kibana)
// Каждый сервис логирует с уникальным correlationId
@Component
public class CorrelationIdFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) {
String correlationId = UUID.randomUUID().toString();
MDC.put("correlationId", correlationId);
try {
filterChain.doFilter(request, response);
} finally {
MDC.remove("correlationId");
}
}
}
Развёртывание
Docker контейнеризация:
FROM openjdk:11-jre-slim
WORKDIR /app
COPY target/user-service.jar app.jar
EXPOSE 8001
ENTRYPOINT ["java", "-jar", "app.jar"]
Kubernetes оркестрация:
apiVersion: apps/v1
kind: Deployment
metadata:
name: user-service
spec:
replicas: 3
template:
spec:
containers:
- name: user-service
image: user-service:1.0.0
ports:
- containerPort: 8001
env:
- name: DATABASE_URL
valueFrom:
configMapKeyRef:
name: app-config
key: database_url
Итог
8 микросервисов в моём проекте демонстрировали:
- Масштабируемость — каждый сервис может масштабироваться независимо
- Разделение ответственности — каждый сервис имеет одну основную задачу
- Независимое развёртывание — можно обновлять сервисы без остановки других
- Технологическую гибкость — разные сервисы могут использовать разные технологии
- Операционную сложность — требуется централизованное логирование, мониторинг, управление конфигурацией