예전에 작성한 글을 옮겨왔습니다.
RabbitMQ는 오픈소스 AMQP(Advanced Message Queueing Protocol, 표준 메세지 큐 프로토콜) 브로커이다.
클라이언트가 메시지 미들웨어 브로커와 통신할 수 있게 해주는 메세징 프로토콜이다.
Broker
Producers -> [Exchange -- (Binding) --> Queue] -> Consumers
Producer: 메세지를 발행하여 Broker의 Exchange로 메세지 전달
Broker: Exchange에서 받은 메세지를 Binding 규칙에 의해 연결된 Queue로 메세지 복사. consumer가 조회할 때까지 데이터 저장.
Consumer: Broker의 Queue를 통해 메세지를 받아가서 처리
Direct Exchange: 지정된 routing key를 가진 queue에만 메세지 전달
Fanout Exchange: 알려진 모든 Queue에게 메세지 전달
Topic Exchange: 지정된 패턴 바인딩에 일치한 Queue에게 메세지 전달
Headers Exchange: 헤더에 포함된 key=value의 일치조건에 따라서 메시지 전달
Application - System간의 통신
서버 부하가 많은 작업
부하 분산
데이터 손실 방지
초당 100k 이상의 대용량 이벤트를 처리시에 사용
메세지를 다시 읽을 필요가 있을때도 사용
초당 20+ 메세지를 복잡한 방식으로 컨슈머(worker)에게 라우트 하고 싶을때 사용
메세지당 전달 보장을 해줄필요가 있을때 사용
$ brew install Rabbitmq
$ brew service start rabbitmq
==> Successfully started `rabbitmq` (label: homebrew.mxcl.rabbitmq)
$ ./rabbitmqctl add_user joy.jeong password
Adding user "joy.jeong" ...
$ ./rabbitmqctl set_user_tags joy.jeong administrator
Setting tags for user "joy.jeong" to [administrator] ...
$ ./rabbitmqctl set_permissions -p / joy.jeong ".*" ".*" ".*"
Setting permissions for user "joy.jeong" in vhost "/" ...
compile group: 'com.rabbitmq', name: 'amqp-client', version: '5.7.1'
@Configuration
@EnableRabbit
public class RabbitConfig {
@Bean
public RabbitTemplate rabbitTemplate() {
RabbitTemplate template = new RabbitTemplate(connectionFactory());
template.setMessageConverter(jsonMessageConverter());
return template;
}
@Bean
public CachingConnectionFactory connectionFactory() {
CachingConnectionFactory factory = new CachingConnectionFactory();
factory.setHost("127.0.0.1");
factory.setUsername("joy.jeong");
factory.setPassword("1234");
return factory;
}
@Bean
public SimpleMessageListenerContainer container() {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory());
return container;
}
}
public class Sender {
@Autowired
private RabbitTemplate template;
public void send() {
template.convertAndSend("amq.direct", "foo.bar", "Hello world!");
}
}
@Component
public class Receiver {
@RabbitListener(queues = "hello")
public void receive(Object message) {
System.out.println(message);
}
비동기 처리 필요 -> 이벤트 응모 후 당첨 여부 추후 메세지로 발송
병목 현상 해결
장애 발생시 추후 데이터 재처리(with Dead Letter Queue)
https://www.rabbitmq.com/getstarted.html
https://spring.io/guides/gs/messaging-rabbitmq/
https://skibis.tistory.com/310
https://www.icelancer.com/2016/12/message-queue.html