본문 바로가기

프로그래밍/Spring

Message Queue 시리즈 2편

1> SpringFrameWork ( With AMQP )

// JAVA Type Configuration
@Bean
public ConnectionFactory connectionFactoryToSlack() {
	CachingConnectionFactory connectionFactory = new CachingConnectionFactory("127.0.0.1");
    connectionFactory.setUsername("guest");
    connectionFactory.setPassword("guest");
    connectionFactory.setVirtualHost("/slack");
	return connectionFactory;
}

<!-- XML Type Configuration -->
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:rabbit="http://www.springframework.org/schema/rabbit"
       xsi:schemaLocation="http://www.springframework.org/schema/rabbit
           http://www.springframework.org/schema/rabbit/spring-rabbit.xsd
           http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd">

    <rabbit:queue name="slack" />
    
    <rabbit:listener-container error-handler="testErrorHandler" connection-factory="connectionFactoryToSlack">
    	<rabbit:listener queues="slack" ref="consumer" />
     </rabbit:listener-container>
</beans>

위와 같은 2가지 설정만으로 해당 Queue에대한 Listener를 등록하고 해당 Queue( 여기서는 slack )에 Message가 담기면 consumer 를 호출 하여 처리 하도록 지정이 된다.

Ps. 위의 JAVA 코드 와 XML 를 섞어서 쓴 이유는 그냥.. -_-; 단순한 호기심이며 필요할경우 한쪽(XML이든 JAVA든)으로 설정이 다 가능하다.
 

위와 같이 RabbitMQ 에 대한 접속설정이 마무리가 되면 이제 consumer를 구현하면 되는데 Spring AMQP에서 제공하고 있는 docs 문서를 보면 아래와 같이 onMessage 인터페이스를 구현하여 쓰도록 설명 되어 있어

Spring AMQP Document 중에서

아래의 코드와 같이 개발을 했는데 추후에 Slack 이외에도 Queue의 내용을 보낼 Target이 여러개가 될 수 있어 Consumer 인터페이스를 만들고 Type 따라 여러형태로 사용할 수 있도록 구현하였다

@Component
public class Consumer implements MessageListener{

	private IConsumer consumer;
	
	public void sendData(String ConsumerType , Message sendMsg) throws Exception{
    	// 타입에 따른 Consumer 호출
		this.consumer = new ConsumerFactory().getInstance(ConsumerType);
		this.consumer.sendData(sendMsg);
	}
	
	@Override
	public void onMessage(Message message) {
		// TODO Auto-generated method stub
		
		MessageProperties mp = message.getMessageProperties();
		String consumerType = mp.getHeader("consumerType");
		if(consumerType != null)
		{
			try {
				sendData(consumerType , message);
			}catch(Exception e) {
				e.printStackTrace();
			}
		}
	}
}

 

여기까지 했으면 기본적으로 Slack Queue에 Message가 들어왔을때 Header의 consumer Type에 따라 Consumer 클래스를 통해 Sending을 할 수 있게 되었다.

2> Message 설계 및 Queue의 설계

Message의 설계 와 Queue의 설계 부분이 가장 많은 고민과 시간을 할애했던것 같다.
Message 와 Queue의 설계에 따라 비지니스 로직을 구현할 소스들의 형태가 달라질 수 있기 때문이다.

1) Queue
Queue의 경우는 Rabbit MQ에서 제공하는 다양한 기능들을 먼저 확인 후 진행해야한다
https://skibis.tistory.com/310 해당 블로그의 정보참조

위의 블로그의 설명데로 Direct/Fanout/Topic 등과 같이 Queue로 Message를 Sending 방식에 따라 (Routing, BroadCast) Queue사용에 대한 설계를 할 수 있고 비지니스 로직 구현에도 차이가 발생하게 된다.

결국 위의 Source 에서 보면 Queue의 Naming Rule을 서비스 단위로 하자고 결정이 되어 slack으로 나가는 Message를 담당하는 Queue의 이름을 slack으로 지정하게 되었고 그에따라 위와 같이 consumer를 인터페이스화 하여 코드를 개발하게 되었다.

이부분은 사실 정답이 있는것이 아니라 구성원들의 의견 및 사용하는 각 회사의 시스템 특성에 따라 달라질 것으로
내부 구성원들끼리의 협의를 통해 좋은 결론을 도출하는것으로....

2) Message

Message의 경우도 아래의 화두로 오랫동안 협의를 진행하였는데

Message의 경우는 AMQP에서 제공하는 Message를 그대로 사용할지에 대한 부분과
Message 클래스를 상속받아 회사에 맞춤 Message를 만들어서 사용할지에 대한 부분의 의견이 나왔는데

결국은 AMQP에서 제공하는 Message의 형태를 그대로 사용하는 것으로 결론을 냈다
Ps. 개발공수를 줄이는 방향으로 !!! 

각자 장단점이 있어 이부분을 협의 하고 결정하는데 있어 오랜 시간이 걸렸다.... 
역시 개발보단 ㅠㅠ 의견의 합치는 언제나 어렵다는것을 다시한번 느끼게 되었습니다.....

'프로그래밍 > Spring' 카테고리의 다른 글

Message Queue 시리즈 1편  (0) 2019.10.21