메시지 큐

MOM(Message Oriented MiddleWare) 은 비동기 메시지를 사용하는 다른 응용 프로그램 사이에서 데이터 송수신을 의미.
MOM을 구현한 시스템을 메시지 큐(MQ)라 한다.

메시지 큐의 장점

  1. 비동기 - Queue에 밀어 넣고 추후 처리가 가능하다
  2. 어플리케이션과 분리하여 사용이 가능하다.
  3. 다른 어플리케이션 또는 프로세스에서 큐에 메시지를 보내 통신을 할수 있다.

    JMS란?

    MOM을 자바에서 지원하는 표준 API입니다.

오픈 소스 메시지 큐

RabbitMQ, ActiveMQ, ZeroMQ, Kafka

현재 aws에서 ActiveMQ, Kafka는 풀리하게 지원한다.
RabiitMQ를 aws환경에서 쓰기위해선 별도의 엘리스틱 빈스토크에 올려서 써야한다…. 왜…아직 지원을 안하는거지…

위의 큐 간단한 비교 인기순
https://stackshare.io/stackups/activemq-vs-kafka-vs-rabbitmq

예제를 만들어보자

https://github.com/beanbroker/beanbroker_spring.git 을 클론하면 소스가 있다.

pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!--message q-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-broker</artifactId>
</dependency>

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>

위의 디펜던시 추가

CONSUMER, PRODUCER, LISTENER

Consumer
말그대로 메시지 수신하여 저장

1
2
3
4
5
6
7
8
9
10
11
12
@Component
public class JmsConsumer {
private static Logger log = LoggerFactory.getLogger(JmsConsumer.class);
@Autowired
private MessageStorage customerStorage;

@JmsListener(destination = "${beanbroker.activemq.queue}", containerFactory="jsaFactory")
public void receive(Customer customer){
log.debug("Recieved Message: " + customer);
customerStorage.add(customer);
}
}

Producer
말그대로 메시지를 보냄

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17


@Component
public class JmsProducer {
private static Logger log = LoggerFactory.getLogger(JmsProducer.class);
@Autowired
JmsTemplate jmsTemplate;

@Value("${beanbroker.activemq.queue}")
String queue;

public void send(Customer customer){

log.debug("send data : {} " , customer.toString());
jmsTemplate.convertAndSend(queue, customer);
}
}

Listener

해당 채널 큐에 메시지가 들어옴을 기다리며 들어왔을 경우 작동

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Component
public class JmsListener {


private static Logger log = LoggerFactory.getLogger(JmsListener.class);
@org.springframework.jms.annotation.JmsListener(destination = "beanbroker-queue", containerFactory = "jsaFactory")
public void receiveMessage(Customer customer){

log.info("test {}" , customer.toString());

}
}
```



### MqController

@RestController
public class MqController {

@Autowired
JmsProducer jmsProducer;

@Autowired
private MessageStorage messageStorage;


@PostMapping(value="/mq/customer")
@ResponseStatus(HttpStatus.CREATED)
public Customer postCustomer(@RequestBody Customer customer){
    jmsProducer.send(customer);

    return customer;
}

@GetMapping(value="/mq/customers")
public List<Customer> getAll(){
    List<Customer> customers = messageStorage.getAll();
    return customers;
}

@DeleteMapping(value="/mq/customers/clear")
public String clearCustomerStorage() {
    messageStorage.clear();
    return "Clear All CustomerStorage!";
}

}

`
post시 큐에 적재,
get시 현재 큐에 들어가 있는 데이터 read
delete시 큐에 들어가있는 데이터 clear

메시지 큐를 사용하여 다양한 서비스에 이용할수 있다. 예를들어
데이터를 저장하고 다른 일을 하나의 request에서 다 처리하게 될경우 블록상태가 된다. 자원은 한정적인데 해당 자원을 효율적으로 쓰는 방법을 연구해야 한다.

큐를 사용하면 좋을 것 같은?

  1. 로그를 저장할 경우
    하나의 어플리케이션에서 로그찍을 데이터를 큐에 적재 -> 다른 어플리케이션에서 큐를 listen하다 듣게 될경우 별도의 S3같은 서비스에 저장

  2. 푸쉬서비스
    위의 로그와 동일하게 만들면 될것 같다.

AWS with 큐

aws에서 버튼 몇번만 누르면 생성되는 sqs 서비스가 있다. sqs와 Lamda서비스를 이용하게 될경우 재미난걸 만들어 낼수 있다. sqs를 검색하여 찾아보니 성능이 많이 뛰어나지 않음을 알수 있다. 람다를 쓰게 될경우 노드를 조금만 공부하여 쓰자! 다양한 언어들을 지원하나 자바를 쓸경우 느리다(통계가 그러하다). 파이썬 또는 노드를 선택하여 쓰자