분산 시스템은 여러 대의 컴퓨터 또는 서버가 네트워크를 통해 분산되어 다양한 작업과 구성 요소를 수행하는 모든 환경이다.
분산 시스템은 단일 컴퓨터나 장치가 처리하기에 작업 부하가 너무 클 때 사용된다.
분산시스템을 통해 작업을 효율적으로 분산시켜 성능, 가용성, 확장성을 향상시킬 수 있다.
여러 컴퓨터나 시스템 간에 데이터, 메시지를 교환하고 통신하는 방법이다. 여러 서버에 걸쳐 있는 애플리케이션들이 서로 데이터나 메시지를 주고받을 수 있도록 해준다.
메시지 브로커와의 통합, 메시지 라우팅, 메시지 필터링, 메시지 변환 등의 기능이 있으며 예로 Apache Kafka, RabbitMQ, Amazon Kinesis 등이 있다.
AMQP 는 적합한 클라이언트 애플리케이션이 적합한 메시징 미들웨어 브로커와 통신할 수 있도록 하는 메시징 프로토콜이다.
애플리케이션 간 안정적이고 효율적인 데이터 전송을 위해 설계되었다. 메시지를 비동기적으로 처리하고 분산 시스템에서 안정적으로 데이터를 전송하기 위해 사용된다.
이미지 출처 : https://www.rabbitmq.com/tutorials/amqp-concepts.html
메시지를 생성하고 송신하는 과정이다. 생산자(게시자) Producer(Publisher) 는 메시지를 생성하고 AMQP 클라이언트를 사용하여 메시지를 전송한다.
메시지 라이팅 과정이다. Exchange 에서는 AMQP 브로커를 통해 메시지를 수신하고 라우팅 알고리즘을 사용하여 메시지를 적절한 큐에 전달한다. 이를 위해 브로커는 교환과 대기열이라는 두 가지 주요 구성 요소를 사용한다. 이 AMQP 브로커에 RabbitMQ 가 해당한다.
메시지 저장 과정이다. Queue 에서는 메시지를 저장하며 생산자와 소비자 간의 안정적인 비동기 통신을 처리하도록 돕니다.
메시지 수신 과정이다. AMQP 프로토콜을 통해 메시지를 소비자에게 전달한다. 만약 소비자에게 메시지가 전달되지 않으면 메시지 브로커에서 이를 보관한다.
AMQP 클라이언트 : AMQP 프로토콜을 사용하여 메시지를 생성하고 송신
AMQP 브로커 : AMQP 프로토콜을 사용하여 메시지를 송수신하는 시스템 간의 중개자 역할 수행
분산 시스템에서 메시지, 데이터를 전달하기 위한 중간 매개체로 사용된다. RabbitMQ 는 가볍고 안정적이며 확장 가능하고 이식 가능한 메시지 브로커이다. AMQP 를 통해 통신할 수 있으며 오픈 소스 및 크로스 플랫폼 메시지 브로커이므로 Java, Pythonm Node.js 같은 다양한 프로그래밍 언어와 플랫폼에서 사용할 수 있다.
메시지 큐를 사용하여 메시지의 생산자와 소비자 사이에 비동기적인 통신을 함으로써 메시지는 큐에 저장되어 생산자와 소비자가 독립적으로 작동할 수 있다.
네트워크 프로토콜이기 때문에 게시자, 소비자, 브로커는 모두 서로 다른 시스템에 상주할 수 있다.
다양한 메시징 패턴 지원. 다양한 애플리케이션 및 시스템 가느이 통신을 쉽게 구현 가능
분산형 메시지 큐 시스템으로 클러스터링을 통해 확장이 가능하다. 이를 통해 메시지 처리량을 증가시키고 고가용성을 보장할 수 있다.
메시지를 디스크에 저장하여 안정적으로 보관가능하다. 메시지의 유실을 방지하고 안정적인 메시지 전달을 보장할 수 있다.
AMQP 를 비롯한 다양한 프로토콜을 지원한다. 이를 통해 다양한 플랫폼과 언어로 개발된 애플리케이션과 통신할 수 있다.
RabbitMQ 의 튜토리얼 페이지 를 보면 알 수 있듯 많은 프로그래밍 언어를 지원한다.
다양한 기능을 제공한다. 메시지 라우팅, 우선순위 설정, 토픽 기반 메시징 등을 활용하여 복잡한 메시징 시나리오를 구현할 수 있다.
메시지를 보내는 프로그램. 게시자는 메시지를 RabbitMQ(메시지 브로커) 에 전송한다.
메시지 브로커에 교환기 Exchange, 메시지 큐 Queue 라는 구성요소가 포함되어 있다. 교환은 생산자 Producer 로부터 메시지를 수신하고 이를 0개 이상의 대기열로 라우팅한다. 라우팅 알고리즘은 Exchange 유혀오가 바인딩 규칙에 따라 달라질 수 있다.
Exchange 유형
메시지 라우팅 키를 기반으로 대기열에 메시지를 전달한다. 직접 교환에서 바인딩 키가 메시지의 라우팅 키와 정확히 일치하는 큐로 메시지가 라우팅된다.
이미지 출처 : https://www.tutlane.com/tutorial/rabbitmq/rabbitmq-exchanges
바인딩된 모든 대기열로 메시지를 라우팅한다.
여러 소비자에게 메시지를 브로드캐스트하는데 유용하다.
이미지 출처 : https://www.tutlane.com/tutorial/rabbitmq/rabbitmq-exchanges
라우팅 키와 바인딩에 지정된 라우팅 패턴 간의 와일드카드 일치를 수행하여 큐에 메시지를 게시한다.
이미지 출처 : https://www.tutlane.com/tutorial/rabbitmq/rabbitmq-exchanges
라우팅을 위해 메시지 헤더 속성을 사용한다.
헤더 값은 소비자가 지정한 헤더와 일치해야 메시지가 라우팅된다.
헤더 정보를 기반으로 라우팅하기에 라우팅 키나 패턴 매칭과는 다른 동작을 한다.
이미지 출처 : https://www.tutlane.com/tutorial/rabbitmq/rabbitmq-exchanges
대기열과 교환 간의 관계를 연결하는 과정을 의미한다.
RabbitMQ 에서의 Queue 를 의미하며 교환에서 큐로 전송되는 메시지를 저장하는 버퍼를 말한다. 메시지는 RabbitMQ 와 애플리케이션을 통해 흐르나 대기열에만 저장할 수 있다.
소비 Consume 은 수신 Receive 와 비슷한 의미를 갖는다. 소비자는 주로 메시지 브로커(RabbitMQ) 에서 메시지를 가져와서 수신하고 처리하는 주체를 의미한다. 메시지를 소비하려면 큐가 존재해야 한다.
텍스트, JSON, XML, 바이너리 데이터 등을 담을 수 있다.
메시지의 우선순위를 지정할 수 있어 중요한 메시지에 우선순위를 부여할 수 있다.
메시지를 라우팅하고 필터링하는 기능을 제공하여 메시지를 특정 대기열로 전송하거나 특정 소비자에게 전송할 수 있다.
큐(대기열)의 이름으로 애플리케이션을 참조하는데 사용한다. 이름은 고유해야 하며 시스템상 정의된 이름이 아니어야 한다.
서버 재시작 후에도 유지되는지 여부를 설정하는 속성이다.
이미지 출처 : https://www.tutlane.com/tutorial/rabbitmq/rabbitmq-exchanges
durability 옵션
durable
: 서버 재시작 후에도 대기열이 유지된다.transient
: 서버 재시작 후에 대기열은 유지되지 않는다.큐가 만약 배타적이라면 클라이언트의 연결이 끊어지자마자 큐가 삭제될 것이니 durability 가 아무 영향을 끼칠 수 없다. 이 경우 auto-deleted 큐는 마지막 소비자가 취소되거나 채널이 닫히거나 연결이 끊어질때 삭제된다.
큐에 대기중인 메시지가 없을 때 자동으로 큐를 샂게할지 여부를 설정한다.
메시지가 큐에 얼마 동안 유지될 수 있는지를 설정한다.
이미지 출처 : https://www.tutlane.com/tutorial/rabbitmq/rabbitmq-exchanges
큐의 만료시간을 설정할 수 있고 큐가 자동으로 삭제되기 전까지 얼만큼의 시간동안 사용되지 않아도 되는지 설정한다. 이때 사용되지 않았다는 의미는 큐가 어떤 소비자도 갖지 않고 다시 선언되지 않았다는 것을 의미한다.
이미지 출처 : https://www.tutlane.com/tutorial/rabbitmq/rabbitmq-exchanges
큐에 쌓을 수 있는 메시지의 최대 개수를 제한한다.
x-max-length 인자를 설정하여 사용한다.
이미지 출처 : https://www.tutlane.com/tutorial/rabbitmq/rabbitmq-exchanges
homebrew 로 RabbitMQ 를 설치할 수 있다고 하지만 M1 mac pro 를 사용하면서 homebrew PATH 에 고생했던 기억이 나서 docker 로 설치해줬다.
먼저 docker desktop 을 켜주고 rabbitmq 사이트에서 도커로 rabbitmq 이미지를 받아 설치하는 명령어를 실행해줬다.
docker run -it --rm --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3.12-management
RabbitMQ 가 잘 설치된 모습
일단은 저 명령어를 실행할 때만 RabbitMQ 를 사용할 수 있다고 생각하고 설치 과정을 따라가보자
RabbitMQ 메시지 브로커와 커맨드 라인에서 상호작용할 수 있는 도구를 말한다. 이는 큐 생성, 메시지 발행, 메시지 소비, 교환 관리 같은 작업을 수행하고 RabbitMQ 리소스를 관리하기 위해 사용할 수 있는 다양한 명령어를 제공한다.
rabbitmqctl
: 서비스 관리와 일반적인 운영자 작업을 위한 CLI
이미지 출처 : https://www.rabbitmq.com/rabbitmqctl.8.html
rabbitmqctl 명령어 | 기능 |
---|---|
rabbitmqctl 명령어 | 설명 |
rabbitmqctl start_app | rabbitMQ 애플리케이션 시작 |
rabbitmqctl stop_app | rabbitMQ 애플리케이션 정지 |
rabbitmqctl list_queues | 큐 목록 표시 |
rabbitmqctl list_exchanges | 익스체인지 목록 표시 |
rabbitmqctl list_bindings | 바인딩 목록 표시 |
rabbitmqctl list_connections | 커넥션 목록 표시 |
rabbitmqctl list_channels | 채널 목록 표시 |
rabbitmqctl list_consumers | 컨슈머 목록 표시 |
rabbitmqctl list_vhosts | 가상 호스트 목록 표시 |
rabbitmqctl list_users | 유저 목록 표시 |
rabbitmqctl list_permissions | 퍼미션 목록 표시 |
rabbitmqctl status | 상태 정보 표시 |
rabbitmq 사용자 관련 명령어
rabbitmqctl 명령어 | 명령어 설명 | rabbitmqctl 명령어 응용 |
---|---|---|
rabbitmqctl list_users | 사용자 목록 조회 | |
rabbitmqctl add_user | 사용자 추가 | rabbitmqctl add_user <username> <password> |
rabbitmqctl delete_user | 사용자 삭제 | rabbitmqctl delete_user <username> |
rabbitmqctl change_password | 사용자 비밀번호 변경 | rabbitmqctl change_password <username> <new_password> |
rabbitmqctl set_user_tags | 사용자 태그 설정 | rabbitmqctl set_user_tags <username> <tag> |
rabbitmqctl clear_user_tags | 사용자 태그 제거 | rabbitmqctl clear_user_tags <username> |
rabbitmqctl set_permissions -p | 사용자 권한 설정 | rabbitmqctl set_permissions -p <vhost> <username> <conf> <write> <read> |
rabbitmqctl clear_permissions -p | 사용자 권한 제거 | rabbitmqctl clear_permissions -p <vhost> <username> |
아래 초기 로컬 RabbitMQ 경로로 접속
http://localhost:15672
기본 사용자 아이디와 비번은 id - guest, pw - guest 이다.
이후 rabbitmq cli 를 사용하려 했더니
rabbitmqctl add_user admin admin
zsh: command not found: rabbitmqctl
라고 뜬다. 생각해보니 로컬상에 rabbitmq 를 설치한게 아니라 도커 가상머신 위에 rabbimq 이미지와 컨테이너를 받아 사용중이라 docker exec 에 rabbitmq 라는 컨테이너에서 abbitmqctl add_user admin admin 이라는 명령어를 쳐줘~! 같은 형식으로 실행하니 잘 동작한다.
// 사용자 아이디, 비번 - admin admin 으로 생성한다.
docker exec rabbitmq rabbitmqctl add_user admin admin
// 사용자 리스트를 조회한다.
docker exec rabbitmq rabbitmqctl list_users
// 사용자에 대해 권한 부여
docker exec rabbitmq rabbitmqctl set_user_tags admin administrator
권한 종류
Admin : RabbitMQ 의 모든 권한을 갖고 있고 모든 동작을 수행할 수 있다.
Monitoring : RabbitMQ 의 상태 및 성능에 대한 모니터링 수행 가능
Policymaker : RabbitMQ 의 정책을 관리하고 설정 가능
Management : RabbitMQ 의 관리 작업 수행
Impersonator : 다른 사용자로서 RabbitMQ 에 대한 동작 수행
None : 어떤 권한도 갖고 있지 않다.
논리적인 메시지 브로커를 나타내는 개념을 의미한다.
가상 호스트를 사용시 RabbitMQ 서버에서 독립된 메시지 브로커를 구성가능하다.
각 가상호스트는 독립된 사용자, 교환기, 큐, 권한을 가지고 있다. 이를 통해 여러 개의 독립된 애플리케이션 혹은 팀이 RabbitMQ 를 사용할 수 있다.
docker exec rabbitmq rabbitmqctl list_permissions
docker exec rabbitmq rabbitmqctl set_permissions -p / "admin" ".*" ".*" ".*"
웹의 Admin 탭에서 사용자 목록을 확인 및 관리할 수 있다.
개인적으로 application.properties 는 가독성이 별로 안좋아서 yml 형식을 좋아한다.
spring:
# Spring Boot RabbitMQ 설정
rabbitmq:
host: localhost
port: 5672
username: admin
password: admin
속성 명 | 설명 |
---|---|
spring.rabbitmq.host | RabbitMQ 호스트 주소 |
spring.rabbitmq.port | RabbitMQ 포트 번호 |
spring.rabbitmq.username | RabbitMQ 연결에 사용되는 사용자 이름 |
spring.rabbitmq.password | RabbitMQ 연결에 사용되는 비밀번호 |
spring.rabbitmq.virtual-host | RabbitMQ 가상 호스트 이름 |
spring.rabbitmq.listener.simple.concurrency | 간단한 리스너의 동시성 수준 |
spring.rabbitmq.template.exchange | RabbitMQ 템플릿의 기본 교환기 이름 |
spring.rabbitmq.template.routing-key | RabbitMQ 템플릿의 기본 라우팅 키 |
앞에서 살펴봤던 것처럼 producer 는 메시지를 생성하고 메시지 브로커에게 전송하는 역할을 한다. 메세지를 전송하는 프로그램은 producer 이다.
rabbitMQ 사이트에서 튜토리얼을 따라해보자
처음 가장 간단한 예제가 Hello World 를 전송하는 것이고 이를 메일을 전송하는 것에 비유하고 있다. 메일을 작성한 우리는 producer 이다. 이 메일을 담은 우체통은 RabbitMQ 이고 우리는 언젠가 이 메일이 수신자에게 도달할 것이라 확신한다. 메일을 받는 사람은 consumer 이다.
다음 예시에서는 AMQP 0-9-1 프로토콜을 사용하는데 이는 일반적으로 메세지를 보내는데 사용되는 프로토콜이다.
# application.yml
spring:
# Spring Boot RabbitMQ 설정
rabbitmq:
host: localhost
port: 5672
username: admin
password: admin
profiles:
active: usage_message
logging:
level:
org: ERROR
tutorial:
client:
duration: 10000
producer (sender) 가 메세지를 RabbitMQ 메세징 브로커에 전달하여 큐에 저장하라는 명령을 전달했다.
java -jar build/libs/rabbitmqTest-0.0.1-SNAPSHOT.jar --spring.profiles.active=hello-world,sender
그러니 큐가 생성되었고 다음 명령어를 통해 소비자 consumer 가 메세지를 수신하니
java -jar build/libs/rabbitmqTest-0.0.1-SNAPSHOT.jar --spring.profiles.active=hello-world,receiver
큐에 저장되었던 메세지를 빼내 소비자에게 전달된 모습을 확인할 수 있다.
아직 소비자가 메세지를 수신하기 전에 rabbitmqctl list_queues 명령어를 통해 현재 큐에 어떤 메세지들이 쌓여 있는지 확인할 수 있었다.
rabbitmq docs 를 따라서 해보는 것은 처음이었는데 설명이 정말 잘 되어있다. 그리고 contributor9 님의 포스트에 정말 상세히 설명이 나와있어서 따라서 만들어보기 용이했다. 3편의 내용은 아직 한번에 이해가 되지 않아 다음 포스트에서 좀더 튜토리얼을 진행해보고 따라서 연습해보려 한다...
Java Spring Boot AMQP RabbitMQ 이해하기 1. 구조 - Contributor9
Java Spring Boot AMQP RabbitMQ 이해하기 2. 로컬 환경 구성 - Contributor9
Java Spring Boot AMQP RabbitMQ 이해하기 3. Java 구축 및 간단 예제 - Contributor9
tutlane tutorial rabbitmq
rabbitmq concept
rabbitmq rabbitmqctl 명령어
rabbitmq tutorial github repo