어느날 갑자기 평상시에 잘 작동하던 rabbitmq 서버가 갑자기 접속이 되지 않는 커넥션 오류를 마구 뿜어내기 시작했습니다. 다행히 운영이 아니라 테스트환경이었지만 커넥션 오류가 발생한 경우는 처음이었습니다. 기존에 잘 작동했던 시스템인데 커넥션 오류가 떠서 연계되어 있던 api 와 배치 서비스가 정상적으로 구동되지 않는 상황이었어요.
큐 서버의 대시보드를 확인하니 위 상황처럼 엄청난 큐가 쌓여있고 메모리도 설정된 수준을 넘어 full 로 차있는 상황이었습니다. 메세지 큐 서버의 커넥션 정보를 보니 모든 커넥션이 blocked 혹은 blocking 상태였어요. block 상태인 요청을 취소하고 다시 요청을 넣으면 connection 리스트에는 들어가지만 동일하게 blocked 이나 blocking 상태로 정상적인 커넥션이 생성되지 않는 증상을 보였습니다.
추측하기로는 메모리가 이미 제한된 수준(5.4GB watermark)을 넘어서 여유 메모리가 없기 때문에 신규 커넥션이 계속 block 되고 정상적으로 running 상태로 전환되지 않는 것으로 보였습니다. 실제로 rabbitmq 문서를 보면 아래와 같이 resource 가 낮을때 커넥션을 block 시킨다고 설명하고 있습니다.
큐가 과도하게 쌓인 것은 내부적으로 엄청난 큐가 들어오는 속도에 대비해 처리하는 속도가 따라가지 못해 계속 쌓인 듯 했습니다. 테스트 환경이지만 msa 환경에서 다양한 서비스들이 Virtual Host 를 생성하여 수백개의 channel 을 만들어 큐를 이용하고 있어서 어떤 서비스에서 큐를 적체시켰는지 특정하기는 어려웠습니다.
어쩔 수 없이 위 오류를 해결하기 위해 일단 큐서비스를 재기동하였고, 다행히 메모리가 정상적으로 돌아왔습니다. 메모리가 정상적으로 돌아오니 커넥션도 다시 running 상태가 되면서 api 와 배치 서비스가 정상화되었네요.
메세지큐 서버를 이용하면서 메모리 때문에 커넥션이 정상적으로 연결되지 않을 수 있다는 걸 처음 알았네요. 운영이 아니라 테스트 환경이어서 다행이었던 점도 있지만, 만약에 이런 동일한 상황이 운영에서 발생했을 경우에 동일한 장애가 나지 않을 방법에 대해서 생각해볼 좋은 계기였던 것 같습니다.
메모리가 가득 차서 만약 동일한 환경에서 해당 오류를 해결하려면 서버의 재기동 밖에 방법이 없는데, 이럴 경우에는 이미 들어와 있던 방대한 큐들이 모두 유실되는 위험이 있습니다. 이런 경우를 대비하기 위해서 큐를 RDBMS 나 파일서버 등등 단순히 메모리에만 저장하는 것이 아니라 백업할 수 있는 방법을 고려해봐야겠습니다. 백업이 있다면 메모리 풀로 인한 큐서버의 재기동 이슈에서 좀 더 다양한 선택을 할 수 있을 것 같네요.