99 Ngày Spring — Ngày 79: RabbitMQ với Spring
RabbitMQ nhận message vào exchange, định tuyến qua binding tới queue, rồi giao cho consumer. Nó hợp với hàng đợi công việc và routing linh hoạt. Spring AMQP cung cấp RabbitTemplate và @RabbitListener; nhưng xác nhận, retry và dead-letter vẫn phải thiết kế theo nghiệp vụ.

1. Exchange, binding và queue
Direct exchange định tuyến theo routing key khớp; topic exchange hỗ trợ pattern; fanout phát tới mọi queue đã bind. Queue giữ message chờ consumer. Durable exchange/queue và persistent message giúp qua restart, nhưng publisher còn cần confirm để biết broker thực sự nhận. Nếu message không route được, cấu hình mandatory/returns hoặc alternate exchange.
@Bean DirectExchange ordersExchange() { return new DirectExchange("orders.x"); }
@Bean Queue invoicesQueue() { return QueueBuilder.durable("invoices.q").build(); }
@Bean Binding invoicesBinding(Queue q, DirectExchange x) {
return BindingBuilder.bind(q).to(x).with("order.paid");
}2. Gửi và nhận bằng Spring AMQP
RabbitTemplate.convertAndSend gửi vào exchange với routing key. @RabbitListener tiêu thụ từ queue; nhiều consumer cùng queue chia việc, không phải mỗi consumer đều nhận một bản. Đặt converter rõ ràng để hai phía hiểu cùng schema. Phương thức listener nên idempotent vì message có thể được giao lại khi lỗi hoặc kết nối mất.
@Bean MessageConverter jsonConverter() {
return new Jackson2JsonMessageConverter();
}
rabbitTemplate.convertAndSend("orders.x", "order.paid", event);
@RabbitListener(queues = "invoices.q")
void createInvoice(OrderPaid event) {
invoiceService.createOnce(event.eventId(), event.orderId());
}3. Retry, ack và dead-letter exchange
Nếu listener ném lỗi, container xử lý theo cấu hình retry/requeue; requeue mãi tạo vòng lặp nóng. Giới hạn số lần thử, backoff, rồi reject tới dead-letter exchange đã cấu hình cho queue. Quan sát số message ready/unacked và DLQ. Chỉ ack sau khi side effect thành công; idempotency bảo vệ trường hợp side effect đã xong nhưng ack bị mất.
spring.rabbitmq.listener.simple.retry.enabled=true
spring.rabbitmq.listener.simple.retry.max-attempts=3
spring.rabbitmq.listener.simple.retry.initial-interval=1s
# Configure a dead-letter exchange on the source queue.4. RabbitMQ hay Kafka?
RabbitMQ hợp tác vụ được giao đến queue và routing theo key/pattern. Kafka hợp luồng sự kiện lưu theo log, consumer group độc lập, replay theo offset và lượng dữ liệu lớn. Hai hệ thống đều cần schema, idempotency và quan sát lỗi. Chọn theo yêu cầu replay, fan-out, ordering, retention và vận hành; không chọn vì tên công nghệ đang phổ biến.
Cần replay lịch sử theo offset: cân nhắc Kafka.
Cần định tuyến tác vụ linh hoạt tới queue: cân nhắc RabbitMQ.
RabbitMQ và Kafka giải những bài toán khác nhau nhưng cùng có giao lại message. Ngày 80 nối sự kiện với dữ liệu bằng outbox, saga và idempotency.
Tài liệu đối chiếu
https://docs.spring.io/spring-boot/reference/messaging/amqp.html
https://docs.spring.io/spring-amqp/reference/amqp/receiving-messages/async-annotation-driven.html
Site Admin
Engineer and writer. Building things with TypeScript and distributed systems.
Bình luận (0)
Bạn cần đăng nhập bằng Google để bình luận.
Hãy là người bình luận đầu tiên.


