Time Wait Socket은 무엇일까요

kkambbak1·2024년 3월 11일

4 way handshake로 연결을 종료할 때,

클라이언트가 ACK를 보내고 FIN-WAIT -> TIME-WAIT 상태로 변경된다.

실제 Socket이 종료되는 시기는

클라이언트: TIME-WAIT의 타임아웃(2MSL) 후 CLOSED 된다.
서버: ACK를 수신한 후 바로 CLOSED 된다.

TIME_WAIT 이란 TCP 상태의 가장 마지막 단계

Active Close 즉, 먼저 close()를 요청한 곳에서 최종적으로 남게 되며, 2MSL(Maximum Segment Lifetime) 유지됩니다.

Time Wait Socket의 주요 목적
1. 패킷의 잔여 복사본을 피하기 위해 이전 연결의 패킷이 네트워크에서 완전히 사라질 때까지 기다리는 것 (지연 패킷이 발생해 잘못된 데이터를 처리할 수도 있기 때문.)
2. 즉, 이전 연결의 모든 패킷이 사라질 때까지 다른 포트에서 동일한 연결을 열어서는 안 됨.
3. 이전 연결의 종료에 대한 확인 응답을 받지 못한 경우, 다른 쪽에서 이전 연결을 다시 열려고 할 때 충돌을 방지하기 위해 일정 시간 동안 기다림(연결이 닫혔는지 확인해야할 경우)

즉,
1. 지연패킷으로 인한 패킷 손실이나 충돌 방지
2. 연결이 제대로 닫혔는지 확인

Time Wait 상태는 TCP의 신뢰성을 보장하기 위해 중요하다.

RFC 793 에는 TIME_WAIT을 2 MSL로 규정했으며 CentOS 6에서는 60초 동안 유지됩니다. 아울러 이 값은 조정할 수 없습니다.

읽어봐야되는 글

https://tech.kakao.com/2016/04/21/closewait-timewait/#part-ii-time_wait
https://docs.likejazz.com/time-wait/

가장 아래의 정리글을 가져왔습니다.

TCP/IP Illustrated를 쓴 리차드 스티븐스의 또 다른 책 Unix Network Programming에는 이런 구절2이 있다.

The TIME_WAIT state is our friend and is there to help us (i.e., to let old duplicate segments expire in the network). Instead of trying to avoid the state, we should understand it.

TIME_WAIT은 우리를 도와주는 친구다. 네트워크에서 오래된 중복 세그먼트를 날려주는 훌륭한 역할을 한다. 자꾸 없애려고 노력하지 말고 이해해야 한다.


TIME_WAIT은 패킷의 오동작을 막아주는 우리의 친구같은 존재다.

수 많은 잘못된 정보들 사이에서 아래와 같은 올바른 정보를 반드시 기억해두길 바란다.

  • TIME_WAIT의 타임아웃은 60초로 하드 코딩되어 있다. 설정할 수 없다.
  • 다수의 TIME_WAIT이 서버 성능을 저하시킨다는 논문5은 1997년에 출판됐다. 지금은 2016년이다. 20년이 지났다.
  • 클라이언트가 서버 투 서버로 한 서버에 요청이 많을 경우 tcp_tw_reuse 옵션을 설정해 TIME_WAIT을 재사용하도록 한다. 서버는 해당 사항이 없다.
  • 오래된 서버인 경우 클라이언트가 서버 투 서버 통신을 많이 한다면 빈 포트 스캔으로 성능 저하가 발생하므로 마찬가지로 tcp_tw_reuse 옵션을 설정한다.
  • tcp_tw_reuse와 SO_REUSEADDR는 서로 다른 소켓에 적용되는 옵션이다.
  • 서버/클라이언트 모두 tcp_timestamps가 기본값인 켜져 있어야 하며, 끄면 안되고 끌 필요도 없다.
  • net.ipv4.tcp_fin_timeout은 90 정도로 설정한다.
  • FIN_WAIT1은 상대방 OS에 문제가 있는 경우다.
  • FIN_WAIT2는 상대방 어플리케이션에 문제가 있는 경우다.
  • FIN_WAIT2는 TIME_WAIT의 역할을 대행한다.
  • 특수한 경우가 아니면 링거 옵션은 사용하지 않는다.
  • 서버가 클라이언트를 accept() 할때 할당하는 것은 소켓이다. 포트가 아니다.
  • 소켓의 최대 갯수는 65,535개가 아니다. 소켓은 <protocol>, <src addr>, <src port>, <dest addr>, <dest port> 5개의 값으로 유니크하게 구성되며, 서버 포트 또는 클라이언트의 IP가 추가될 경우 그 만큼의 새로운 쌍을 생성할 수 있다.

TL;DR

  • 서버는 아무것도 할 필요가 없다.
  • 클라이언트는 net.ipv4.tcp_tw_reuse를 1로 설정한다.
  • 서버와 클라이언트가 NAT 없이 1:1 로 직접 연결되어 있다면 압도적인 성능을 보이는 net.ipv4.tcp_tw_recycle을 적극 활용한다.
profile
윤성

0개의 댓글