아래의 링크의 글을 읽고 오시면 이 글을 읽는데 도움이 됩니다.(아마도?)
MQTT 적용을 통한 중계시스템 개선

조만간 Mqtt를 사용하는 새로운 업주용 솔루션이 늦어도 올해안에는 출시될 예정입니다. 그동안 RESTFul API 기반의 주문정보 조회시스템은 안정적으로 잘 동작했으나 Multi Agent기반으로 확장하기에는 태생적인 한계로 몇가지 문제점을 안고 있었는데요.

RESTFul API는 Connection이 유지된 상태가 아니므로 서버에서 즉시 클라이언트로 정보를 전달할 수 없고 (이것이 가장 큰 문제) Multi Client기반으로 데이터를 전달하기 위해서는 등록되어 있는 클라이언트에 대칭되는 데이터를 서버에 준비해야 합니다.
또한 이 데이터를 클라이언트가 중복되거나 누락되는 일 없이 전달되도록 치밀하게 처리해야 합니다. 예를 들면
클라이언트가 접속하기 전 생성된 데이터를 받을 수 있도록 서버 정보를 갱신해야 할지 라던가 클라이언트가 받아가지 않고 종료된 데이터를 어떻게 삭제해야 할 지를 고민해야 하죠. (물론 이런 문제는 Mqtt를 사용하더라도 Plan B로 처리해야 합니다.)

Mqtt를 사용하기로 결정이 나고 서버를 올렸으나 이것은 적어도 우아한형제들에서는 한번도 적용해 본 적이 없는 새로운 시스템. 아무도 얼마나 성능이 나올지 얼마나 안정적으로 돌릴 수 있을지 감이 없습니다. 하여 간단히(?) 테스트 프로그램을 작성해서 스트레스 테스트를 해보기로 했습니다.

테스트를 위해서는 아래와 같은 기능이 필요했습니다.

  • 최대한 서로 다른 IP 대역으로 테스트 클라이언트를 돌릴 수 있으면 좋겠다.
  • 각각의 Mqtt 클라이언트에 메세지를 보내 처리해 볼 수 있으면 좋겠다.
  • 메세지가 잘 갔는지 확인할 수 있었으면 좋겠다.

대충 Controller를 하나 만들고 그 프로그램이 Mqtt Client를 생성하는 프로그램을 실행하게 하자. PC당 대충 2000개쯤 만들면 되겠지 라고 생각하고 테스트 코드 작성.

첫번째 시스템

느려!!!

돌아가는 모양새를 보니 프로세스를 생성하는 부분이 부하가 있거나 Windows Form생성부분에서 부하가 있는것으로 보입니다. 나중에 생각해보니 메모리를 프로세스당 1M만 써도 2000대면 2G가 되더군요.(이래서 수학을 열심히 해야 합니다.) 1000대 정도는 어떻게 되는 것 같은데 2000대는 도저히 테스트 할 수 있는 상태가 아닙니다. PC당 1000 Connection을 처리하면 예상 테스트 수치 30000대를 처리하려면 PC가 30대가 있어야 합니다. 프로세스당 1개의 Connection을 처리하던 Mqtt Client를 Client당 10개의 Connection을 생성하도록 변경합니다. 적당히 200개 정도 생성하도록 하여 PC당 2000 Connection을 테스트 할 수 있게 되었습니다.
초안1


테스트를 수행하다 보니 접속과 종료를 빈번하게 테스트 해야 하는데 이걸 일일이 사람이 처리해야 하는게 너무 귀찮습니다. 테스트를 용이하게 하기 위해 Controller에도 Mqtt를 붙여봅니다.
두번째 시스템

  • 클라이언트를 일괄적으로 컨트롤 할 수 있도록 하자.

이제 프로그램만 띄워 놓으면 일괄적으로 테스트를 수행할 수 있게 되었습니다.

테스트를 하다보니 문제점이 발생합니다. Mqtt서버가 다운되니 Controller에 붙어있는 Mqtt까지 같이 다운되어 통제불능 상태가 됩니다. 서로 서버를 분리해야 할 필요가 있습니다. Controller에 서버정보를 고정으로 심고 Stress Test에 사용할 서버정보는 테스트 실행 메세지에 전송하도록 합니다.
세번째 시스템

  • 변경이 필요한 내용은 모두 옵션으로 받을 수 있도록 하자.
  • Control Channel과 Test Channel을 분리하자.

초안2

테스트 하고 나면 Mqtt Client당 하나씩의 로그를 저장하도록 했습니다. 이 로그를 정리해서 봐야 할 필요가 생겼습니다. 일일이 부탁해서 로그를 취합해도 되지만 이미 PC접수 로그수집을 위해 사용하는 채널을 이미 AWS S3에 운영하고 있으니 이곳에 모아보기로 합니다.
세번째 시스템

  • 테스트 로그를 한곳에서 취합할 수 있도록 하자.

하여 개략적인 전체 구성도는 아래와 같습니다. 전체구성도

결론 아직 계속 튜닝을 진행하고 있는 단계여서 결론을 내리기엔 성급하지만 Mqtt는 ‘가벼운 클라이언트’를 위해 서버는 많은 일을 하고 있는 것으로 보입니다. 몇만대 수준의 Connection을 이루기 위해서는 서버의 튜닝과 더불어 클라이언트의 subscribe와 ping과 같은 부분도 세심하게 조절해야 할 것 같습니다. 테스트 일정이 뒤로 밀리면서 테스트가 끝나지 않았는데 글을 발행하게 되었습니다. 다음에 기회가 되면 After Service로 찾아뵙도록 하겠습니다.