- 이벤트 기반 통신은, 여러 서비스 및 관련 도메인 모델에 변경 사항이나 메시지들을 전파할 때 중요하다.
- 변경사항이 발생했을 경우, 여러 서비스/모델 에서 변경 사항을 적용 할 방법이 필요
- 메시지큐를 사용하면 안정적인 통신과 기능적용이 가능하다
- 메시지큐에는 여러가지가 있지만, 이번에는 ActiveMQ를 사용한다
- Event-driven communication is important when propagating changes or messages across multiple services and related domain models.
- When changes occur, a method is needed to apply those changes across multiple services/models.
- Using a message queue enables reliable communication and feature implementation.
- There are various message queues available, but this time we will use ActiveMQ.
Event 기반 통신 / 아키텍처
이벤트기반 통신은 여러 마이크로 서비스 및 관련 도메인 모델에 변경사항을 전파 할 때 중요하다
변경 사항이 발생했을 경우, 여러 서비스/모델 에서 변경 사항을 적용 할 방법이 필요하다
이벤트 기반 아키텍처를 달성하기 위한 방법은 여러가지가 있지만, 많은 경우에 메시징 패턴을 사용한다
RabbitMQ, ActiveMQ, Apache Kafka 등과 같은 도구들은 메시징 패턴에 사용되는 메시지 브로커이다
이 중, ActiveMQ를 사용해 메시지를 보내고 받아보려고 한다
Event-Driven Communication / Architecture
Event-driven communication is important when propagating changes across multiple microservices and related domain models.
When changes occur, a method is needed to apply those changes across multiple services/models.
There are various ways to achieve event-driven architecture, but in many cases, messaging patterns are used.
Tools such as RabbitMQ, ActiveMQ, and Apache Kafka are message brokers used for messaging patterns.
Among these, we will try sending and receiving messages using ActiveMQ.
ActiveMQ 세팅하기
ActiveMQ는 메시지 브로커로써 메시지를 보내고 받을 수 있는 기능을 제공한다
ActiveMQ는 공식페이지에서 다운받아도 괜찮고, docker-compose 를 통해서 설치해도 된다
공식페이지에서 다운받으려면, 아래 페이지에서 사용하면 된다
- ActiveMQ 공식페이지 링크: http://activemq.apache.org/activemq-5151-release.html
나는 개발환경에 따로 설치하는 것 보다, docker를 선호해서 docker-compose를 사용하려고 한다
Setting Up ActiveMQ
ActiveMQ is a message broker that provides the ability to send and receive messages.
You can download ActiveMQ from the official page or install it via docker-compose.
To download from the official page, use the link below:
- ActiveMQ official page link: http://activemq.apache.org/activemq-5151-release.html
I prefer using Docker over installing separately in my development environment, so I will use docker-compose.
version: '3'
services:
activemq:
image: rmohr/activemq
container_name: activemq
ports:
- "8161:8161"
- "1883:1883"
- "5672:5672"
- "61613:61613"
- "61616:61616"
- "61614:61614"
- ActiveMQ Web Console은 8161, ActiveMQ Broker는 61616 포트를 사용한다
- 기타 다른 1883, 5672, 61613, 61614 포트는 다른 프로토콜을 사용한다
- docker 로그를 확인하면 ActiveMQ의 포트를 모두 확인할 수 있다
- ActiveMQ Web Console uses port 8161, and ActiveMQ Broker uses port 61616.
- Other ports 1883, 5672, 61613, 61614 are used for different protocols.
- You can check all ActiveMQ ports by viewing the docker logs.
SpringBoot 프로젝트 만들기
- springboot 버전은 2.7.9-SNAPSHOT 버전을 사용한다
Creating a SpringBoot Project
- We will use SpringBoot version 2.7.9-SNAPSHOT.
plugins {
id 'java'
id 'org.springframework.boot' version '2.7.9-SNAPSHOT'
id 'io.spring.dependency-management' version '1.0.15.RELEASE'
}
SpringBoot Gradle 적용
- spring web과 activemq 를 넣는다
Applying SpringBoot Gradle
- Add spring web and activemq dependencies.
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-activemq'
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
SpringBoot Resource 설정
- resources/application.properties 파일 내부에 ActiveMQ의 설정을 넣는다
SpringBoot Resource Configuration
- Add the ActiveMQ configuration inside the resources/application.properties file.
spring.activemq.broker-url=tcp://localhost:61616
spring.activemq.user=admin
spring.activemq.password=admin
SpringBoot Application 작성하기
Writing the SpringBoot Application
Config
- Config 패키지를 만들고, 아래의 JmsCOnfig 클래스를 만든다
Config
- Create a Config package and create the JmsConfig class as shown below.
package com.example.springbootactivemq.config;
import org.apache.activemq.command.ActiveMQQueue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.jms.Queue;
@Configuration
public class JmsConfig {
@Bean
public Queue queue() {
return new ActiveMQQueue("test-queue");
}
}
consumer
- consumer 패키지를 만들고, 아래와같이 컨슈머를 만든다
consumer
- Create a consumer package and create the consumer as shown below.
package com.example.springbootactivemq.consumer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Component;
@Component
public class MessageConsumer {
private final Logger logger = LoggerFactory.getLogger(MessageConsumer.class);
@JmsListener(destination = "test-queue")
public void receiveMessage(String message) {
logger.info("Received message: {}", message);
}
@JmsListener(destination = "test-queue")
@SendTo("greet-queue")
public String receiveMessageAndReply(String message) {
logger.info("Received message: {}", message);
return "Hello " + message;
}
@JmsListener(destination = "greet-queue")
public void receiveGreeting(String message) {
logger.info("Received greeting: {}", message);
}
}
@JmsListener를 통해서 메시지를 받는다.test-queue라는 큐에 메시지가 들어오면,receiveMessage메소드가 실행된다@SendTo를 통해서 메시지를 보낼 수 있다.test-queue라는 큐에 메시지가 들어오면,receiveMessageAndReply메소드가 실행된다@SendTo에 지정한greet-queue큐에 메시지를 보낸다
receiveGreeting메소드는greet-queue라는 큐에 메시지가 들어오면 실행된다
- Messages are received through
@JmsListener. When a message enters thetest-queue, thereceiveMessagemethod is executed. - Messages can be sent through
@SendTo. When a message enters thetest-queue, thereceiveMessageAndReplymethod is executed.- It sends a message to the
greet-queuespecified in@SendTo.
- It sends a message to the
- The
receiveGreetingmethod is executed when a message enters thegreet-queue.
controller
- controller를 만들어 API를 통해 Message를 보내는 역할을 만든다
controller
- Create a controller to handle sending messages through the API.
package com.example.springbootactivemq.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.jms.Queue;
@RestController
@RequestMapping("/api")
public class MessageController {
@Autowired
private Queue queue;
@Autowired
private JmsTemplate jmsTemplate;
@GetMapping("message/{message}")
public ResponseEntity<String> publishMessage(@PathVariable("message") final String message) {
jmsTemplate.convertAndSend(queue, message);
return new ResponseEntity(message, HttpStatus.OK);
}
}
실행
/api/message/hello를 호출하면,test-queue에 메시지가 들어가고,greet-queue에 메시지가 들어간다- 이 모든 과정을
ActiveMQ Web Console에서 볼 수 있다
Execution
- When you call
/api/message/hello, a message enters thetest-queue, and then a message enters thegreet-queue. - You can view this entire process in the
ActiveMQ Web Console.