프로젝트를 하던 중 pub/sub
를 비동기화 처리해야 하는 상황이 생겼다.
메세지 처리 방식
1.mqtt
로 메세지를publish
한다.
2. 정해진 시간(10s)동안 해당 메세지에 대한 응답 메세지가 오지 않으면disable
처리한다.
위의 우리 팀이 정한 메세지 처리 방식
를 수행하기 위해서 다음과 같이 처리하려고 했다.
- 메세지를
publish
한다.publish
한 메세지를public static final hashSet<deviceId, fileId> buffer
에 등록한다.Thread.sleep(10000)
한다mqtt
로 들어온 응답 메세지를subscribe
하면buffer
에 등록된 메세지를 지운다.- 10초 후,
awake
된 스레드가buffer
에 있는device
들을 대상으로 상태를 변경한다.
Thread.sleep
를 하자 10초가 지나기 전까지는 요청에 대한 응답을 받지 못하는 상황이 되어버렸다.기본적으로 WAS는 multithread를 지원한다. servletcontext
에서 servlet
을 싱글톤으로 관리하며 thread pool
를 이용해 요청마다 thread
를 할당시키는 방식이다.
그렇기 때문에 changeDeviceStatus
를 비동기화 처리하지 않아도 로직은 문제 없이 작동하지만, 처음 클라이언트의 publish
요청에 대한 API 응답을 10초 동안 받지 못하는 문제가 발생했다.
mqtt
를 publish
하면 MqttPahoMessageHandler
가 연결을 잃어버리는 에러가 발생했다.o.s.i.m.outbound.MqttPahoMessageHandler : Lost connection; will attempt reconnect on next request
Thread.sleep
를 하자 10초가 지나기 전까지는 처리에 대한 요청를 받지 못하는 상황이 되어버렸다.changeDeviceStatus
메서드를 비동기화 처리하는 것으로 해당 문제를 해결했다. @Async
어노테이션을 이용하면 해당 메서드를 비동기처리 할 수 있기 때문에 응답을 받기 위해서 스레드가 깨어날때까지 기다릴 필요가 없어진다.
@EnableAsync
를 걸어주고, 비동기 처리를 하고 싶은 메서드에 @Async
를 달아주면 된다. 자세한 내용은 참고한 블로그를 이용하자..
mqtt
를 publish
하면 MqttPahoMessageHandler
가 연결을 잃어버리는 에러가 발생했다.사실 이 문제는 동기화 처리를 하기 전에도 발생했던 문제였지만, 애써 무시하고 있었다. publish
처리를 하고 나면 연결을 잃어버리기 때문에 일정 시간동안 mqtt
를 이용한 pub/sub
을 모두 사용할 수 없었다.
메세지를 pubish
한 후에 10초 안에 subscribe
를 하도록 변경된 상황에서는 이 문제를 꼭 해결해야만 했다. 오랜 구글링 결과 깃허브 를 통해서 문제의 원인을 찾을 수 있었다. 너무 친절하게 설명해주셨다..
pub/sub
에 동일한 client-id
를 사용했기 때문이었다.
pub/sub
에 동일한 client-id
를 사용하고 있는 걸 확인할 수 있다.
pub/sub
각각 다른 client-id
를 사용해줌으로써 이 문제는 간단하게 해결되었다. 해결 방법을 찾는건 오래 걸렸는데 해결하는건 너무 간단했다.