[Spring Project] 비동기화 처리 & mqtt 연결 장애

신명철·2022년 5월 8일
0

etc

목록 보기
4/5

들어가며

프로젝트를 하던 중 pub/sub를 비동기화 처리해야 하는 상황이 생겼다.

메세지 처리 방식
1. mqtt 로 메세지를 publish 한다.
2. 정해진 시간(10s)동안 해당 메세지에 대한 응답 메세지가 오지 않으면 disable 처리한다.


문제 발생

위의 우리 팀이 정한 메세지 처리 방식 를 수행하기 위해서 다음과 같이 처리하려고 했다.

  1. 메세지를 publish 한다.
  2. publish 한 메세지를 public static final hashSet<deviceId, fileId> buffer 에 등록한다.
  3. Thread.sleep(10000) 한다
  4. mqtt 로 들어온 응답 메세지를 subscribe 하면 buffer에 등록된 메세지를 지운다.
  5. 10초 후, awake 된 스레드가 buffer에 있는 device들을 대상으로 상태를 변경한다.

1. Thread.sleep를 하자 10초가 지나기 전까지는 요청에 대한 응답을 받지 못하는 상황이 되어버렸다.

기본적으로 WAS는 multithread를 지원한다. servletcontext에서 servlet을 싱글톤으로 관리하며 thread pool를 이용해 요청마다 thread 를 할당시키는 방식이다.

그렇기 때문에 changeDeviceStatus를 비동기화 처리하지 않아도 로직은 문제 없이 작동하지만, 처음 클라이언트의 publish 요청에 대한 API 응답을 10초 동안 받지 못하는 문제가 발생했다.

2. mqttpublish 하면 MqttPahoMessageHandler가 연결을 잃어버리는 에러가 발생했다.

o.s.i.m.outbound.MqttPahoMessageHandler  : Lost connection; will attempt reconnect on next request

문제 해결

1. Thread.sleep를 하자 10초가 지나기 전까지는 처리에 대한 요청를 받지 못하는 상황이 되어버렸다.

changeDeviceStatus 메서드를 비동기화 처리하는 것으로 해당 문제를 해결했다. @Async 어노테이션을 이용하면 해당 메서드를 비동기처리 할 수 있기 때문에 응답을 받기 위해서 스레드가 깨어날때까지 기다릴 필요가 없어진다.

@EnableAsync를 걸어주고, 비동기 처리를 하고 싶은 메서드에 @Async를 달아주면 된다. 자세한 내용은 참고한 블로그를 이용하자..

2. mqttpublish 하면 MqttPahoMessageHandler가 연결을 잃어버리는 에러가 발생했다.

사실 이 문제는 동기화 처리를 하기 전에도 발생했던 문제였지만, 애써 무시하고 있었다. publish 처리를 하고 나면 연결을 잃어버리기 때문에 일정 시간동안 mqtt를 이용한 pub/sub을 모두 사용할 수 없었다.

메세지를 pubish 한 후에 10초 안에 subscribe를 하도록 변경된 상황에서는 이 문제를 꼭 해결해야만 했다. 오랜 구글링 결과 깃허브 를 통해서 문제의 원인을 찾을 수 있었다. 너무 친절하게 설명해주셨다..

pub/sub에 동일한 client-id를 사용했기 때문이었다.

pub/sub에 동일한 client-id를 사용하고 있는 걸 확인할 수 있다.

pub/sub 각각 다른 client-id를 사용해줌으로써 이 문제는 간단하게 해결되었다. 해결 방법을 찾는건 오래 걸렸는데 해결하는건 너무 간단했다.


profile
내 머릿속 지우개

0개의 댓글