Какие операции записи микросервиса использовались на последней работе
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Операции записи микросервиса на последней работе
Для Java разработчика с опытом, практическое применение микросервисной архитектуры — это критически важный навык. На последней работе я был глубоко вовлечён в разработку и оптимизацию операций записи в микросервисной системе.
1. Синхронная запись с REST API
Основной механизм для операций записи был синхронный HTTP REST API:
@RestController
@RequestMapping("/api/v1/orders")
public class OrderController {
private final OrderService orderService;
@PostMapping
public ResponseEntity<OrderResponse> createOrder(
@Valid @RequestBody CreateOrderRequest request) {
Order order = orderService.createOrder(request);
return ResponseEntity.status(HttpStatus.CREATED)
.body(OrderResponse.from(order));
}
@PutMapping("/{id}/status")
public ResponseEntity<OrderResponse> updateOrderStatus(
@PathVariable Long id,
@Valid @RequestBody UpdateStatusRequest request) {
Order order = orderService.updateOrderStatus(id, request.getStatus());
return ResponseEntity.ok(OrderResponse.from(order));
}
}
Преимущества этого подхода:
- Простота реализации
- Синхронный response с немедленной confirmацией
- Лёгкий debugging
- Стандартный REST pattern
2. Асинхронная запись через message queue (RabbitMQ)
Для операций, не требующих немедленного ответа, мы использовали RabbitMQ и Spring AMQP:
@Service
public class OrderEventPublisher {
private final RabbitTemplate rabbitTemplate;
private static final String EXCHANGE = "orders.exchange";
private static final String ROUTING_KEY = "orders.created";
public void publishOrderCreated(Order order) {
OrderEvent event = new OrderEvent(
order.getId(),
order.getCustomerId(),
order.getTotalAmount(),
LocalDateTime.now()
);
rabbitTemplate.convertAndSend(
EXCHANGE,
ROUTING_KEY,
event
);
}
}
@Service
public class OrderEventConsumer {
private final EmailService emailService;
private final NotificationService notificationService;
@RabbitListener(queues = "orders.created.queue")
public void handleOrderCreated(OrderEvent event) {
// Отправить Email клиенту
emailService.sendOrderConfirmation(event.getCustomerId(), event.getOrderId());
// Отправить Notification
notificationService.notifyOrderCreated(event.getCustomerId());
// Обновить Analytics
analyticsService.recordOrderEvent(event);
}
}
Этот подход использовался для:
- Отправки Email и SMS уведомлений
- Обновления Analytics и Business Intelligence
- Синхронизации с внешними системами
- Обработки computationally expensive операций
3. Saga pattern для distributed transactions
Для сложных операций, затрагивающих несколько микросервисов, мы реализовали Saga pattern:
@Service
public class OrderSagaOrchestrator {
private final OrderService orderService;
private final PaymentServiceClient paymentClient;
private final InventoryServiceClient inventoryClient;
private final ShippingServiceClient shippingClient;
@Transactional
public OrderResponse createOrderWithSaga(CreateOrderRequest request) {
// Step 1: Create Order
Order order = orderService.createOrder(request);
try {
// Step 2: Reserve Inventory
inventoryClient.reserveItems(order.getItems());
// Step 3: Process Payment
PaymentResult paymentResult = paymentClient.processPayment(
order.getId(),
order.getTotalAmount(),
request.getPaymentDetails()
);
if (!paymentResult.isSuccessful()) {
throw new PaymentFailedException(paymentResult.getMessage());
}
// Step 4: Create Shipping
ShippingResult shippingResult = shippingClient.createShipment(
order.getId(),
order.getDeliveryAddress()
);
// Step 5: Confirm Order
orderService.confirmOrder(order.getId());
return OrderResponse.from(orderService.getOrder(order.getId()));
} catch (Exception e) {
// Compensating transactions (rollback)
handleSagaFailure(order, e);
throw new OrderCreationFailedException(e.getMessage());
}
}
private void handleSagaFailure(Order order, Exception e) {
try {
// Отменить reservation
inventoryClient.releaseItems(order.getItems());
// Отменить платёж (refund)
paymentClient.refund(order.getId());
// Отменить shipment
shippingClient.cancelShipment(order.getId());
// Обновить статус заказа
orderService.rejectOrder(order.getId(), e.getMessage());
} catch (Exception compensationError) {
logger.error("Failed to compensate order {}", order.getId(), compensationError);
// Отправить alert для manual intervention
notificationService.alertAdmins("Saga compensation failed for order " + order.getId());
}
}
}
4. Spring Cloud OpenFeign для inter-service communication
Для синхронного общения между микросервисами использовали Feign клиент:
@FeignClient(name = "payment-service", url = "${payment-service.url}")
public interface PaymentServiceClient {
@PostMapping("/api/v1/payments")
PaymentResponse createPayment(
@RequestBody CreatePaymentRequest request
);
@PostMapping("/api/v1/payments/{id}/refund")
RefundResponse refund(
@PathVariable String id,
@RequestBody RefundRequest request
);
}
@Service
public class PaymentService {
private final PaymentServiceClient paymentClient;
private final CircuitBreaker circuitBreaker;
public PaymentResponse processPayment(PaymentRequest request) {
try {
// Вызов с circuit breaker protection
return circuitBreaker.executeSupplier(() ->
paymentClient.createPayment(request)
);
} catch (CircuitBreakerOpenException e) {
logger.error("Payment service unavailable");
throw new PaymentServiceUnavailableException("Payment service is down");
}
}
}
5. Database Write Patterns
Event Sourcing
Для audit trail и полной истории всех операций:
@Service
public class OrderEventStore {
private final OrderEventRepository eventRepository;
public void recordOrderEvent(OrderEvent event) {
event.setTimestamp(LocalDateTime.now(UTC));
event.setVersion(getCurrentVersion() + 1);
eventRepository.save(event);
}
}
public class OrderEvent {
private Long orderId;
private String eventType; // CREATED, UPDATED, CANCELLED, SHIPPED
private LocalDateTime timestamp;
private int version;
private String payload; // JSON с полными данными события
}
CQRS (Command Query Responsibility Segregation)
Разделение операций чтения и записи:
// Command side - Write
@Service
public class OrderCommandHandler {
private final OrderRepository writeRepository;
private final OrderEventStore eventStore;
public void handleCreateOrderCommand(CreateOrderCommand command) {
Order order = Order.create(command);
writeRepository.save(order);
eventStore.recordOrderEvent(
new OrderCreatedEvent(order.getId(), command)
);
}
}
// Query side - Read (read-optimized model)
@Service
public class OrderQueryService {
private final OrderReadModelRepository readRepository;
public OrderReadModel getOrderDetails(Long orderId) {
return readRepository.findById(orderId)
.orElseThrow(() -> new OrderNotFoundException(orderId));
}
}
6. Batch Write Operations
Для высокопроизводительных операций массовой записи:
@Service
public class OrderBatchProcessor {
private final OrderRepository orderRepository;
private final BatchSize batchSize = 1000;
@Transactional
public void processBatchOrders(List<CreateOrderRequest> requests) {
int processed = 0;
for (int i = 0; i < requests.size(); i += batchSize) {
int end = Math.min(i + batchSize, requests.size());
List<Order> batch = requests.subList(i, end)
.stream()
.map(Order::from)
.collect(Collectors.toList());
orderRepository.saveAll(batch);
// Flush и clear для оптимизации памяти
entityManager.flush();
entityManager.clear();
processed += batch.size();
logger.info("Processed {} orders out of {}", processed, requests.size());
}
}
}
7. Write-ahead Logging (WAL)
Для гарантирования durability:
@Service
public class WriteAheadLogger {
private final WriteLogRepository logRepository;
private final OrderRepository orderRepository;
@Transactional
public void writeWithLogging(Order order) {
// Step 1: Write to log first
WriteLogEntry logEntry = new WriteLogEntry(
"ORDER_CREATE",
order.getId(),
order.toJson(),
LocalDateTime.now(UTC)
);
logRepository.save(logEntry);
// Step 2: Write actual data
orderRepository.save(order);
// Step 3: Mark log entry as committed
logRepository.markAsCommitted(logEntry.getId());
}
}
8. Idempotency Keys
Для защиты от дублирования при retry операций:
@RestController
@RequestMapping("/api/v1/orders")
public class OrderController {
private final OrderService orderService;
private final IdempotencyKeyStore keyStore;
@PostMapping
public ResponseEntity<OrderResponse> createOrder(
@Valid @RequestBody CreateOrderRequest request,
@RequestHeader("X-Idempotency-Key") String idempotencyKey) {
// Check if we already processed this request
Optional<OrderResponse> cached = keyStore.get(idempotencyKey);
if (cached.isPresent()) {
return ResponseEntity.ok(cached.get());
}
// Process order
Order order = orderService.createOrder(request);
OrderResponse response = OrderResponse.from(order);
// Store result for future retries
keyStore.store(idempotencyKey, response);
return ResponseEntity.status(HttpStatus.CREATED).body(response);
}
}
9. Monitoring и Observability
Для отслеживания операций записи:
@Aspect
@Service
public class WriteOperationAspect {
private final MeterRegistry meterRegistry;
@Around("@annotation(WriteOperation)")
public Object trackWriteOperation(ProceedingJoinPoint joinPoint) throws Throwable {
Timer.Sample sample = Timer.start(meterRegistry);
try {
Object result = joinPoint.proceed();
meterRegistry.counter("write.operations.success").increment();
return result;
} catch (Exception e) {
meterRegistry.counter("write.operations.error",
"exception", e.getClass().getSimpleName()).increment();
throw e;
} finally {
sample.stop(Timer.builder("write.operation.duration")
.publishPercentiles(0.5, 0.95, 0.99)
.record(meterRegistry));
}
}
}
Резюме операций записи
Микросервисная архитектура требует различных паттернов для операций записи:
- REST API — для синхронных операций
- Message Queues — для асинхронных операций
- Saga Pattern — для distributed transactions
- Event Sourcing — для полной audit trail
- CQRS — для разделения read/write моделей
- Batch Processing — для массовых операций
- Write-ahead Logging — для durability
- Idempotency Keys — для защиты от дублей
- Monitoring — для наблюдаемости операций
Эти паттерны вместе обеспечивают надёжность, масштабируемость и maintainability микросервисной системы.