본문 바로가기
허브 살리기 프로젝트

TCP, HTTP/HTTPS keep-alive

by jay-choe 2024. 2. 5.

Persistent Connection

클라이언트에서 서버로 데이터를 전송하기 위해 TCP 요청은 client와 서버간 3-way handshake 과정을 통해서 연결을 맺고 데이터를 전송하고 전송이 완료되었으면 4-way handshake 과정을 통해서 해당 연결을 종료한다.

 

 

커넥션을 맺기 위해서는 클라이언트와 서버 관점에서 보면 다음과 같은 작업으로 진행된다.

  • 클라이언트
    • 운영체제로부터 소켓 할당 (사용 할 포트, 파일 디스크립터 등등)
    • 요청 보낼 곳 DNS Query (캐시에 존재하면 캐시를 조회)
    • 소켓 생성
    • 3-way handshake 시작
    • 요청 전송
    • 다 보낸 이후 4-way handshake 시작
    • 커넥션 종료
  • 서버
    • 운영체제로부터 소켓 할당(사용 포트, 파일 디스크립터 등등)
    • 소켓 생성
    • 클라이언트 요청과 연결
    • 요청 응답
    • 4-way handshake 이후 연결 종료

1번의 요청을 하기까지 생각보다 많은 작업이 있다. 물론 해당 내용은 HTTP 기준이며 HTTPS 사용 시 암호화 과정까지 추가된다.

 

지금은 모두가 당연하게 생각하고 있는 부분이지만 여기서 궁금증이 생기는데

 

통신을 위해서는 저 과정은 필연적이지만 하나의 커넥션을 안 닫고 쓰면 계속 데이터만 주고받기만 할 수 있고
효율적이지 않을까? 라는 생각이다.

 

그래서 한 커넥션으로 계속 데이터를 주고 받는 Persistent Connection 이란 개념이 존재한다.

 

이는 HTTP/HTTPS 헤더의 keep-alive 속성을 통해서 설정 할 수 있다.

 

 

 

keep-alive 속성은 TCP쪽과 keep-alive와 HTTP/HTTPS쪽 둘 다 존재해서 이에 관한 차이를 정리해보면

 

TCP keep-alive 에서는 4계층 이므로 해당 커넥션 관점만 바라보니까 해당 커넥션을 어떻게 지속 할 지에 관한 내용을 정의하며

HTTP/HTTPS는 응용 계층이니까 해당 연결을 어떻게 설정 할 지에 관한 내용을 정의한다.

 

즉 TCP에서는 커넥션을 관리하는 측면이고 HTTP/HTTPS쪽은 어떻게 얼마만큼 연결을 유지할지에 관한 응용 레벨이다.

 

TCP에서는 해당 연결을 지속 할 지 여부를 설정 할 수 있는 것이고 이에 관한 다양한 옵션들이 있다.
리눅스에서는 다음과 같은 설정 값들이 있다.

  • net.ipv4.tcp_keepalive_time=600 (얼마나 지속 할 지)
  • net.ipv4.tcp_keepalive_intvl=60 (패킷 재전송 횟수 시간 간격)
  • net.ipv4.tcp_keepalive_probes=10 (패킷 재전송 횟수)

 

TCP에서는 keepalive_time 만큼 지속 한 후 probe 횟수 만큼 해당 커넥션이 지속되고 있는지 확인되는 패킷을 intvl 간격으로 보낸다. 만약 probes 만큼 보냈을 때 지속되지 않다고 판단되면 해당 커넥션을 제거한다.

 

이 설정은 좀비 커넥션을 회수하는데도 유용하다.

 

예를들어 데이터를 보내는 과정에서 클라이언트 오류로 커넥션이 유실되며 4-way handshake 과정을 진행하지 못 한다면

 

서버쪽에서는 계속 해당 소켓이 열린 상태를 유지해야 하지만 keep-alive 시간 이후에 해당 패킷이 전송이 실패하게 되면서 자동으로 커넥션은 제거가 된다.

 

즉 커넥션 관리에도 유용한 설정이다.

 

한편 HTTP/HTTPS 에서는 연결을 keep-alive로 설정 할 지에 관한 내용을 정의한다.

 

이는 HTTP 헤더에 Connection 속성에 Keep-Alive를 명시해주면서 해당 커넥션은 지속하는 것으로 나타낼 수 있다.
추가로 커넥션에 타임아웃 속성(timeout)과 한 커넥션으로 몇 번까지 요청을 보낼 수 있는지도(max) 정의한다.

 

다음은 HTTP 헤더의 예시이다.

 

 

정리하면 TCP쪽 keep-alive 설정은 해당 커넥션이 지속되는지 여부를 확인하고 관리하는 것에 관련 된 내용이고

HTTP/HTTPS쪽 keep-alive 설정은 해당 커넥션을 얼마만큼 지속하는지에 관한 설정에 관련 된 내용이다.

 

예시를 통해서 정리해보면 keep-alive 설정의 동작 방식은 다음과 같다.

 

HTTP/HTTPS에서 keep-alive 설정을 통해 120초의 timeout을 주었고 서버에서 처리가 130초가 걸린다고 가정 해보고

TCP 설정에서 keep-alive 설정을 60초 간격을 10초 probe 횟수를 2번으로 설정했다고 했을 때

 

커넥션을 맺고 데이터를 보내다가 60초가 지났을 때 keep-alive probe 패킷을 보낸다.

커넥션이 유지되고 있으므로 정상 응답을 받기 때문에 해당 커넥션은 다시 유지 된다.

 

120초가 지났을 때 HTTP/HTTPS에서 설정한 타임아웃이 지났기 때문에 클라이언트가 커넥션을 끊는다.

이런 과정으로 해당 커넥션은 제거가 되는 구조이다.

 

 

 

참고