[rabbitmq] pika에서 TCP keepalive 설정하기

owlur·2021년 7월 30일
1

파이썬에서 rabbitmq의 브로커에 연결할때 보통 pika 를 사용한다

이 때 아래의 2가지 상황이 섞이면 문제가 생긴다

  • rabbitmq를 클러스터로 구성하고 로드밸런서로 묶음
  • 클라이언트에서 브로커로 부터 메시지를 받고 상당히 오랜시간의 작업 후 ack 또는 새롭게 데이터를 받아올 때

보통 2번째 처럼 한번에 긴 작업을 할경우 heartbeat를 굉장히 길게 잡거나 0으로 설정하게 되는데 그럼에도 일정시간 후 tcp연결이 비정상적으로 끊기고 브로커와 클라이언트에서 소켓연결이 끊겼음을 인지하지 못하면(fin을 받지 못함) 아래의 상황을 의심해봐야한다

로드밸런서의 idle timeout 기능이 설정되어 있는지 확인해보자!

로드밸런서에서는 유휴한 연결을 일정시간이 지나면 자동으로 해제하는 idle timeout 기능을 제공하는데 이 기능이 설정되어 있을 가능성이 매우 높다

이 경우 heartbeat로는 해결할 수 없다

rabbitmq의 heartbeat 값은 timeout시간이며 timeout/2 초마다 패킷을 보내게 된다. 이를 idle timeout시간 전에 보내도록 적절한 값을 넣으면 로드밸런서에서 연결을 끊지는 않는다
하지만 클라이언트에서 idle timeout 시간보다 2배이상 걸리는 작업을 수행하게 되면 위의 방법으로는 세션을 유지할 수 없다

이 때 TCP keepalive 기능을 사용하면 주기적으로 패킷을 보내게 되면서 해결할 수 있지만 pika 문서에서는 적절한 가이드를 찾지 못 했고 검색해도 나오지가 않았는데

다행히 pika github테스트코드에서 예시를 찾아볼 수 있었다 ConnectionParameters의 tcp_options에 딕셔너리로 TCP_KEEPIDLE, TCP_KEEPCNT, TCP_KEEPINTVL 중 1개이상을 설정해주면 TCP keepalive가 설정된다

credentials = pika.PlainCredentials(USERNAME, PASSWORD)
parameters = pika.ConnectionParameters(HOST,
                                       PORT,
                                       VHOST,
                                       credentials, 
                                       heartbeat=0,
                                       tcp_options={'TCP_KEEPIDLE':60})
connection = pika.BlockingConnection(parameters)
profile
개발자

0개의 댓글