
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

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