Spring Boot ile RabbitMQ: Mikro Servislerde Asenkron İletişim

Spring Boot ile RabbitMQ: Mikro Servislerde Asenkron İletişim
https://learn.microsoft.com/de-de/dotnet/architecture/microservices/multi-container-microservice-net-applications/rabbitmq-event-bus-development-test-environment
Zelkulon07 Mart 20251 dk okuma

RabbitMQ'nun mikro servisleri nasıl ayrıştırdığı, mesajları güvenilir şekilde ilettiği ve Spring AMQP'nin entegrasyonu nasıl kolaylaştırdığı.

Senkron İletişimin Sorunu

Senkron İletişimin Sorunu

Kavramlar: Exchange, Queue, Binding

Kavramlar: Exchange, Queue, Binding
  • Exchange: Mesajları alır ve hangi queue'ya gideceğine karar verir
  • Queue: Bir consumer alana kadar mesajları saklar
  • Binding: Exchange'i queue'ya bağlar (routing key aracılığıyla)
  • Routing Key: Yönlendirme için string anahtar (örn. order.created)

Yapılandırma: Exchange'ler & Queue'lar

@Configuration
public class RabbitMQConfig {

    public static final String ORDER_EXCHANGE    = "order.exchange";
    public static final String ORDER_CREATED_QUEUE = "order.created.queue";
    public static final String ORDER_CREATED_KEY   = "order.created";

    @Bean
    public TopicExchange orderExchange() {
        return new TopicExchange(ORDER_EXCHANGE, true, false);
    }

    @Bean
    public Queue orderCreatedQueue() {
        return QueueBuilder.durable(ORDER_CREATED_QUEUE)
                .withArgument("x-dead-letter-exchange", "")
                .withArgument("x-dead-letter-routing-key", "dead.letter.queue")
                .build();
    }

    @Bean
    public MessageConverter jsonMessageConverter() {
        return new Jackson2JsonMessageConverter();
    }
}

Producer: Mesaj Gönderme

@Service
@RequiredArgsConstructor
public class OrderEventPublisher {

    private final RabbitTemplate rabbitTemplate;

    public void publishOrderCreated(Order order) {
        var event = new OrderCreatedEvent(
            order.getId(), order.getCustomerId(),
            order.getTotalAmount(), Instant.now()
        );
        rabbitTemplate.convertAndSend(
            RabbitMQConfig.ORDER_EXCHANGE,
            RabbitMQConfig.ORDER_CREATED_KEY,
            event
        );
    }
}

// Önemli: event'i yalnızca DB commit'inden SONRA gönder!
@Transactional
public OrderResponse placeOrder(OrderRequest request) {
    Order saved = orderRepository.save(buildOrder(request));
    TransactionSynchronizationManager.registerSynchronization(
        new TransactionSynchronizationAdapter() {
            @Override public void afterCommit() {
                eventPublisher.publishOrderCreated(saved);
            }
        }
    );
    return toResponse(saved);
}

Consumer: Mesaj Alma

@Component
@RequiredArgsConstructor
public class OrderCreatedListener {

    @RabbitListener(queues = RabbitMQConfig.ORDER_CREATED_QUEUE)
    public void handleOrderCreated(
            OrderCreatedEvent event,
            Channel channel,
            @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag
    ) {
        try {
            paymentService.processPayment(event);
            channel.basicAck(deliveryTag, false);   // Başarılı

        } catch (PaymentException e) {
            // Yeniden denenemiyor → Dead Letter Queue
            channel.basicNack(deliveryTag, false, false);

        } catch (Exception e) {
            // Yeniden dene → queue'ya geri
            channel.basicNack(deliveryTag, false, true);
        }
    }
}

Özet

  • Ayrıştırma: servisler birbirini tanımaz
  • Hata toleransı: mesajlar servis kesintilerini atlatır
  • Dead Letter Queue: işlem hatalarında veri kaybı yok
  • Ölçeklenebilirlik: birden fazla consumer örneği paralel işler
  • İşlem güvenliği: event'i yalnızca DB commit'inden sonra gönder
Spring Boot ile RabbitMQ: Mikro Servislerde Asenkron İletişim