ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • TCP Keepalive
    SystemEngineering/Network 2021. 7. 12. 00:15

    개요

    특정 고객사에서 애플리케이션에서 Timeout Exception이 발생하고 RST 반환 개수가 많다는 문의가 들어왔다.

    정리 하는 글이 이 고객사의 직접적인 원인은 아닌 것으로 판단되나, 공부한 김에 정리해 두려한다.

    HTTP Keepalive

    갑자기 HTTP keepalive가 왜 나오는지 의아할 수 있다. 하지만 꽤 많은 사람이 tcp keepalive와 구분하지 못한다. 해당 되지 않는다면 건너뛰어도 좋은 내용이다.

     

    HTTP keepalive는 Apache / Nginx 등의 웹 애플리케이션의 keepalive timeout을 의미한다.

    TCP keepalive와는 다르게, timeout 설정 시간 동안 요청(Request)이 없으면 연결을 자발적으로 끊는다.

    → HTTP keepalive timout이 LB의 유휴 제한시간

    보다 짧으면, LB는 애플리케이션과의 세션이 끊긴 지 모르고

        동일한 서버에 Request를 전달하지만, 이미 끊긴 세션에 대한 요청은 서버에서 504 Error를 던진다.

    즉, HTTP keepalive timeout은 LB의 유휴 제한 시간보다 길게 잡아야 좋다.

    TCP Keepalive

    TCP keepalive는 커널 파라미터로 소켓 통신 간에 두 종단 간의 연결을 유지 시켜준다. net.ipv4.tcp_keepalive_time 설정 값 주기로 keep-alive 소켓을 보내 응답이 오면 연결을 더 유지한다.

    → 정리하자면 소켓 간에 패킷을 주기적으로 던져서 요청이 없더라고 억지로 연결을 유지시키는 것이다.

    즉, TCP Keepalive time이 LB의 유휴 제한시간보다 짧아야 종단 간의 Connection을 유휴 제한시간 보다 더 길게 가져갈 수 있고 좀비 커넥션을 예방 할 수 있다.

     

    [TCP Keepalive 설정 확인]

    $ sudo sysctl -a | grep -i keepalive
    net.ipv4.tcp_keepalive_intvl = 75
    net.ipv4.tcp_keepalive_probes = 9
    net.ipv4.tcp_keepalive_time = 7200

     

    문제의 고객사 서버 구조는 아래와 같다. 물론 구조의 일부이지만 우리가 다룰 내용에 필요한 구조만 보려한다.

    (고객사의 구성도가 아니며, 일반적인 Clustering된 애플리케이션의 구조이다.)

     

    NLB의 유휴 제한 시간은 350s이다. 이건 다른 ELB와 다르게 수정할 수 없는 부분이다. 그러므로 350s뒤에는 NLB의 세션이 초기화되고 Server 1의 Request가 Server 2로 갈 수 있으며 이에 따라 RST를 반환할 가능성이 크다.

    NLB와 ALB의 차이점

    NLB와 ALB의 차이점은 유휴 제한 시간이 지날때의 행동이 다르다.

     

    NLB는 유휴 제한시간이 350s 고정이며, 이 350s가 지나면 Client와 Server 아무에게도 알리지 않고 조용히 세션을 지워버린다. 하여, 서버는 이를 알 방법이 없기에 소켓을 유지한다. 소켓이 생성되지 않은 서버는 handshake가 이뤄지지도 않은 친구가 요청 부터하게 되니 RST를 보낸다.

     

    ALB는 이 NLB와 약간의 차이가 있다. ALB는 유휴 제한 시간 수정이 가능하며, 이 설정한 유휴 제한시간이 지나게되면 Client와 Server에게 FIN을 던져 종단 간의 종료를 알리게된다. 그러므로 소켓은 종료가 되어 RST를 반환하지는 않게된다.

     

    해당 내용의 좋은 글이 있어 가져와 봤다.

    Lessons from AWS NLB Timeouts

    문제 해결

    [TCP_Client_Reset_Count]

    해당 서버의 RST 반환 개수가 타 서버보다 비교적 많은 것을 확인 할 수 있다.

     

    [keepalive_time 설정 값]

     

    위의 설정 값과 같이 net.ipv4.tcp_keepalive_time이 600s로 설정되어 있다. RST를 줄이려면, 350s 미만으로 설정하여 NLB 세션이 끊기기 전에 패킷을 흘려 통신을 유지하면 RST를 줄일 수 있다.

    주의 할 점으로는 이 커널값을 아무리 수정하더라도, 애플리케이션 단의 SO_KEEPALIVE 설정이 되어 있지 않다면 의미가 없다. 커널 값 애플리케이션 설정 값 모두 수정 하도록 한다.

    결론

    • keepalive_time이 ELB의 유휴 제한시간 보다 짧으면 유휴 제한시간보다 연결을 더 길게 유지 할 수 있다.
    • RST는 ELB의 세션이 끊겨 기존에 소켓이 연결되어 있던 서버와 다른 서버로 패킷이 흘러 나타나는 현상이다.
    • 애플리케이션에서 SO_KEEPALIVE 설정이 필요하다.

    댓글

Designed by Tistory.