producer(송신자, 주로 Java기반의 서버)
-> broker
-> queue
-> consumer(수신자, 주로 worker서버 라는 이름으로 불림)
Publisher Confirm은 RabbitMQ에서 메시지가 브로커에 성공적으로 도착했는지를 송신자(Producer)에게 확인해주는 기능입니다. 이를 통해 Producer는 메시지가 브로커에 안전하게 저장되었는지 알 수 있고, 만약 메시지가 도착하지 않았거나 문제가 발생했을 경우 재전송할 수 있는 기회를 갖게 됩니다.
기본적으로 RabbitMQ는 메시지를 브로커에 보내고 나면 송신자에게 별도의 응답을 보내지 않기 때문에, 네트워크 문제나 브로커에서의 장애로 인해 메시지가 유실될 가능성이 있습니다. Publisher Confirm을 사용하면 이러한 상황을 방지할 수 있습니다.
성공(ack)
또는 실패(nack)
응답을 보냅니다.실패 응답(nack)
을 받으면 Producer는 메시지를 재전송하는 등의 처리를 할 수 있습니다.Java에서는 RabbitMQ의 Channel을 "confirm mode"로 설정하여 Publisher Confirm 기능을 사용할 수 있습니다.
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
public class RabbitMQPublisherConfirmExample {
private final static String QUEUE_NAME = "confirm_test_queue";
public static void main(String[] args) throws Exception {
// RabbitMQ에 연결
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
try (Connection connection = factory.newConnection();
Channel channel = connection.createChannel()) {
// 큐 선언 (durable 큐로 설정)
channel.queueDeclare(QUEUE_NAME, true, false, false, null);
// 채널을 confirm mode로 전환
channel.confirmSelect();
String message = "Hello RabbitMQ with Publisher Confirm!";
channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
// 메시지가 성공적으로 브로커에 도달했는지 확인
if (channel.waitForConfirms()) {
System.out.println("Message successfully confirmed by RabbitMQ!");
} else {
System.out.println("Message could not be confirmed. Possible message loss.");
}
}
}
}
channel.confirmSelect()
: 채널을 confirm 모드로 전환합니다. 이를 통해 메시지가 성공적으로 브로커에 도착했는지 확인할 수 있습니다.
channel.basicPublish()
: 메시지를 브로커로 전송합니다.
channel.waitForConfirms()
: 이 메서드는 메시지가 브로커에 정상적으로 도착했는지 기다립니다. 성공하면 true, 실패하면 false를 반환합니다.
비동기 방식으로 Publisher Confirm을 사용할 수도 있습니다. 이 방식은 다수의 메시지를 보내는 환경에서 더 효율적일 수 있습니다.
자바는 기본적으로 동기적으로 작동하는 언어이지만, 비동기적인 프로그래밍을 지원합니다. 특히 멀티스레딩
과 비동기 API(CompletableFuture, 자바 8에서 도입된 비동기 API)
를 통해 자바에서도 비동기 작업을 수행할 수 있습니다.
RabbitMQ에서도 자바로 비동기 Publisher Confirm
을 사용할 수 있으며, 이를 위해 RabbitMQ Java 클라이언트가 비동기적인 ConfirmListener
를 제공합니다. 이를 통해 자바에서도 메시지를 비동기적으로 확인하고 처리할 수 있습니다.
동기적(Synchronous)
: 메서드 호출이 완료될 때까지 호출한 쪽에서 대기하는 방식입니다. 즉, 한 작업이 완료되기 전까지 다음 작업으로 넘어가지 않습니다.
비동기적(Asynchronous)
: 작업을 시작한 후 바로 다음 작업을 진행할 수 있으며, 결과는 나중에 처리됩니다. 자바에서도 멀티스레딩이나 콜백을 사용해 비동기적인 작업을 수행할 수 있습니다.
비동기 Publisher Confirm은 RabbitMQ에서 메시지를 전송한 후, ConfirmListener를 통해 RabbitMQ 브로커로부터 메시지 전송 성공(ack) 또는 실패(nack)에 대한 알림을 비동기적으로 받는 방식입니다. 자바에서도 이 기능을 쉽게 사용할 수 있습니다.
import com.rabbitmq.client.ConfirmListener;
import com.rabbitmq.client.Channel;
public class AsyncPublisherConfirm {
public static void main(String[] args) throws Exception {
// RabbitMQ에 연결 및 채널 생성 (생략)
// 채널을 confirm mode로 전환
channel.confirmSelect();
// 비동기 Confirm Listener 추가
channel.addConfirmListener(new ConfirmListener() {
public void handleAck(long deliveryTag, boolean multiple) {
System.out.println("Message confirmed: " + deliveryTag);
}
public void handleNack(long deliveryTag, boolean multiple) {
System.out.println("Message not confirmed: " + deliveryTag);
}
});
// 메시지 전송
String message = "Message with async confirm";
channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
// 메시지가 확인되는 동안 다른 작업을 수행할 수 있음
}
}
channel.addConfirmListener()
: 비동기로 Publisher Confirm을 처리하기 위해 ConfirmListener를 등록합니다.
handleAck()
: 메시지가 성공적으로 전달되었을 때 호출됩니다.
handleNack()
: 메시지 전송에 실패했을 때 호출됩니다. 실패한 메시지를 처리할 수 있습니다(재전송 등).
메시지 신뢰성 보장
: 메시지가 브로커에 성공적으로 도달했는지 확인할 수 있어, 메시지 유실 방지.
효율성
: 비동기 Confirm을 사용할 경우, 메시지 전송 후 대기하지 않고도 다른 작업을 진행할 수 있습니다.
대용량 처리
: 다수의 메시지를 전송할 때도 효율적으로 확인할 수 있어 대용량 메시지 처리에도 적합합니다.
Publisher Confirm
: 비동기로 처리되기 때문에 성능이 우수하고 대용량 메시지 처리에 적합합니다.
Transaction 모드
: 메시지의 전송을 트랜잭션으로 묶어 처리하므로, 더 강력한 보장을 제공하지만 성능이 낮습니다. Publisher Confirm이 더 가벼운 방식으로 자주 사용됩니다.
Publisher Confirm은 RabbitMQ에서 메시지 유실을 방지하고 메시지가 안전하게 브로커에 도달했는지 확인하는 데 유용한 기능입니다. Producer는 이를 통해 전송한 메시지가 손실되지 않도록 안전하게 관리할 수 있으며, 특히 대용량 메시지 처리 환경에서 성능과 신뢰성을 동시에 보장할 수 있습니다.