본문 바로가기
infra/network

[Network] HTTP Keep-Alive VS TCP Keep-Alive 제대로 알기

by 사바라다 2024. 6. 2.

안녕하세요. 지난 시간에 Apache HttpClient 코드를 분석하면서 Network에 대해서 훑어보는 시간을 가져보았었습니다. 그러면서 Keep-Alive에 대해서 간단히 짚고 넘어갔었는데요. 오늘은 이 Keep-Alive에 대해서 헷갈릴 수 있는 부분들을 정리해보도록 하겠습니다.

개요

Keep-Alive는 Connection을 유지하기 위한 메커니즘입니다. TCP와 Http 모두 Keep-Alive로 Connection을 유지합니다. 둘을 햇갈릴 수 있습니다. 하지만 이 두 Keep-Alive는 완전 다르기 때문에 구분해서 알아둘 필요가 있습니다.

Connection은 너무 오래유지하는 것도 너무 짧게 유지하는것도 모두 리소스적인 낭비로 이어질 수 있습니다. 너무 오래 유지하게 되면 더 이상 사용하지 않는 Connection 이 해제되지 않아서 리소스의 낭비입니다. 반대로 Connection을 너무 짧게 유지하면 모든 요청에 대해서 새로운 Connection을 만들게 되기 때문에 이 또한 리소스의 낭비입니다. 따라서 적절한 Keep-Alive 시간을 유지하는게 중요합니다.

요약

디테일에 들어가기 앞서서 먼저 결론을 짚고 가도록 하겠습니다.

  • TCP Keep-Alive와 Http Keep-Alive는 헷갈릴 수 있으나 완전히 다르기 때문에 구분 필요
  • TCP Keep-Alive
    • TCP 계층에서의 연결을 주기적으로 확인하기 위해서 ACK를 주고 받는 행위
    • ACK을 정상적으로 받지 못하면 OS에서 TCP 연결을 종료
    • OS 에서 관리
  • Http Keep-Alive
    • Http 계층에서 일어나는 Http Connection을 유지하기 위한 메커니즘
    • Keep-Alive 시간 동안 Http 요청을 받지못하면 TCP Connection 종료
    • 기본적으로 종료 시키는 주체는 Web Server
    • Header를 통해서 규약을 지킬 수 있음
    • Application 에서 관리
  • Connection
    • 너무 오래 유지하게 되면 더 이상 사용하지 않는 Connection 이 해제되지 않아서 리소스의 낭비
    • 너무 짧게 유지하면 모든 요청에 대해서 새로운 Connection을 만들게 되기 때문에 리소스의 낭비

상세

Http Keep-Alive

Http Keep-Alive는 HTTP Client와 Server(Web Server) 사이에서 동일한 TCP Connection을 이용해서 여러번 요청을 보내기 위해서 사용합니다. 여러 요청을 하나의 TCP Connection에서 진행하기 때문에 TCP 연결을 위한 3-way Handshake는 첫번째 이후 새롭게 맺지 않습니다. 이렇게 하면 2번째부터는 latency 가 줄어들고 서버 리소스적인 부하도 적게 들게됩니다.

HTTP 서버는 TCP Connection을 Keep-Alive 시간 동안 끊지 않고 기다립니다. 하지만 마지막 요청(Request)로 부터 Keep-Alive 시간이 지난다면 Http 서버(ex. WAS)에서 해당 TCP Connection을 끊습니다. Timeout은 Http 서버에 의해서 관리됩니다.

실제로 Keep-Alive는 Header를 통해서 Client와 Server가 주고 받으며 규약합니다.

HTTP/1.1 200 OK
Connection: Keep-Alive
Keep-Alive: timeout=10, max=500

요청에 대해서 서버에서 위와 같은 응답을 받았습니다. 이것은 아래와 같이 해석할 수 있습니다.

  • Connection: Keep-Alive
    • Keep-Alive로 조건을 만족하면 동일한 TCP Connection을 통해서 다음 요청을 보내겠구나,
  • Keep-Alive: timeout=10, max=500
    • timeout : 지속 시간을 초 단위로 표기, 위의 경우 10초간 지속됨을 알 수 있음
    • max : 연결이 닫히기전에 요청될 수 있는 최대 요청 수
HTTP/1.1 200 OK
Connection: Close

반대로 Keep-Alive를 해당 서버에서 사용하지 못하거나 않는다면 Connection: Close의 형식으로 전달 받을 것입니다.

Reuqest를 보낼 때 Connection Header를 설정해서 보낼 수 있습니다. 하지만 해당 설정은 서버에서의 관리가 메인입니다. 특히, 해당 서버가 Keep-Alive를 지원하지 않을 수 있으며 그렇다면 Keep-Alive를 원한다고 Client에서 요청하더라도 Close 상태로만 반환 될 수 있습니다.

TCP Keep-Alive

TCP KeepAlive는 TCP 연결이 맺어진 이후 해당 연결을 유지하는 것에 대해서 작은 패킷을 보내며 체크하는 매너커즘을 말합니다. 해당 KeepAlive Packet을 통해서 지속적으로 연결이 되어있는지 체크도 하며 만약 Connection이 끊어졌다면 즉시 끊어졌다고 알려주는 역할까지 합니다. 만약 KeepAlive가 없다면 다음 실제 Packet이 전달되기 전 까지 연결이 정상인지 아닌지 알 수 없습니다.

이러한 TCP KeepAlive는 OS의 설정에 의해서 관리되고 있습니다. 아래는 aws에서 linux OS에 대해서 설정하는 값이며 각 설정의 설명은 아래와 같습니다.

net.ipv4.tcp_keepalive_time=200
net.ipv4.tcp_keepalive_intvl=200
net.ipv4.tcp_keepalive_probes=5
  • tcp_keepalive_time : 40 # 최초 keepalive를 보내는 시간
  • tcp_keepalive_probes : 3 # 응답이 없으면 추가로 보내는 횟수
  • tcp_keepalive_intvl : 5 # 추가로 보낼 때의 간격

위 설정이라면 40초 동안 응답이 없는 경우 5초 간격으로 3번의 KeepAlive을 주고 받습니다. 만약 정상적으로 KeepAlive를 주고 받지 못했다면 Connection을 종료합니다.

아래는 WireShark로 찍은 KeepAlive를 주고받은 메시지입니다. 66Byte의 작은 메시지로 연결이 잘 유지되고 있는지 확인하고 있는 패킷을 확인할 수 있었습니다.

참조

반응형

댓글