키키호의 블로그

[Linux] TIME_WAIT 없애기 (tcp_tw_reuse 옵션) 본문

Linux/공통

[Linux] TIME_WAIT 없애기 (tcp_tw_reuse 옵션)

kikiho 2014. 2. 23. 13:42

Linux 는 Kernel Parameters를 이용하여 성능향상을 높일 수 있지만, 그 개수가 너무 많고 의미를 제대로 알지 못한다면, 잘못된 문제로 나타날 수 있습니다.


TCP는 여러개의 State를 가질수 있습니다. 예를들어 CLOSED(연결이 닫혔을때) LISTEN(연결을 기다리고 있을때), ESTABLISHED(연결이 되었을때) 등등의 상태를 가질수 있습니다. 이중에서 TIME_WAIT라는 상태가 있는데, TIME_WAIT 상태는 다음과 같은 경우에 발생합니다. 우선 Client와 Server가 TCP로 연결이 되어 있다고 가정합시다. 이때 클라이언트가 연결을 끊으려면 close함수를 호출합니다. 이 함수를 호출하면 서버에 FIN segment를 보내게 됩니다. 그러면 서버는 이 메시지를 받고 클라이언트가 접속을 끊으려고 하는 것을 알게됩니다. 따라서 서버가 CLOSE_WAIT 상태가 되면서 클라이언트에게 ack segment를 보냅니다. 즉 "네가 접속을 끊는 다는 신호를 받았다" 이런 의미입니다. 이 메시지를 받으면 클라이언트는 FIN_WAIT_2 상태가 됩니다. 이 상태에서 서버는 자신의 socket을 close하고 다시 클라이언트에게 FIN segment를 보냅니다. 즉 자신도 연결을 닫았다는 신호를 클라이언트에게 보내는 것입니다. 이 메시지를 받으면 클라이언트는 ack segment를 보내면서 TIME_WAIT 상태가 됩니다. 즉 서로간의 확인하에 완전히 연결이 끊기게 됩니다. 


TIME_WAIT상태일 경우 해당 포트를 계속 점유하는데, 연결이 빈번한 네트워크 서비스일 경우 연결거부와 관련된 문제가 발생할 수 있다.

MYSQL연결 혹은 웹 Client 연결 등 여러 Case가 있을텐데, 커널단에서 가능한 튜닝 옵션에 대해서 알아보고자 합니다.


1. open 파일 제한 갯수

/proc/sys/fs/file-max 의 값을 늘리면 됩니다.


2. Port 범위 늘리기

대량의 TIME_WAIT가 발생해서 연결을 시도하려는 PORT가 부족할 수가 있다. 클라이언트에 할당될 port의 범위를 늘리는 것으로 어느정도 조정가능하다.

/proc/sys/net/ipv4/ip_local_port_range

보통 32768   61000로 지정되어 있을 것이다. 1024 ~ 65535 로 변경하자.

# echo "1024 ~ 65535" > /proc/sys/net/ipv4/ip_local_port_range

부팅할때 쓰고 싶다면 /etc/rc.local이나 /etc/sysctl.conf 에 추가하여 쓰면 됩니다.

이것은 어디까지나 임시적인 방법으로, 문제를 완전히 해결할 수는 없을 것입니다.


3. Kernel 옵션 조정

소켓이 완전히 닫힐려면 마지막 FIN을 기다려야 하는데, 이 간격을 초단위로 설정할 수 있다. 기본은 60초 정도로 설정되어 있습니다.

net.ipv4.tcp_fin_timeout = 10 ## 기본값은 60 // TCP 연결 상태를 계속 유지하기 위한 시간 설정

net.core.somaxconn = 2048 ## 기본값은 128 // Listen Socket의 Backlog 최대 개수 

 동시에 많은 연결 요청이 수신될 경우 더 큰 값을 사용하면 지원될 수 있는 보류 연결 수가 증가되어 연결 장애를 줄일 수 있습니다.

tcp_tw_reuse=1 ## 기본값은 0 //TCP TIME_WAIT Socket 재사용 여부

 사용하지 않으면, 시스템 과부하시 TIME_WAIT Socket 증가로 인한 local port 소진에 의해 신규 Connection을 생성 못할 수 있다.

 위에 1024 65535로 변경하였지만, 해당포트 자체를 소모할 경우 문제발생할 경우도 있을 것입니다.

tcp_rw_recycle=0 ## 기본값은 0 // TCP TIME_WAIT Socket Recycle 여부

 Packet Reordering이 발생하여 Timestamp 역전 현상이 발생하면, Client로 부터 수신한 SYN Packet이 Drop 된다. 


  tcp_tw_reuse 기능

Server가 TW State에 있을때 Client에서 발송한 Old Packets(어떠한 이유에서든지 재발송 또는 네트워크를 떠돌던 Packets)이 Server에 도달하게 되면 대기시간을 초기화하여 다시 대기하기 시작합니다. 게다가 TW State Session이 존재할 때 Server Process를 재시작 한다던가 하는 방법으로 Binding을 시도한다면 시도한 시점부터 TW State 대기를 재시작하게 됩니다. 따라서 운이 나쁘면 2MSL 보다 훨씬 오랜 시간을 대기하게 됩니다.


이 상황이 일반적인 환경에서는 문제가 되지 않지만 포털의 첫화면이나, 금융권같은 즉시 장애를 복구해야 하는 경우라면 아무것도 해보지 못하고 장애복구에 상당한 시간을 소비하게 되어 타격이 아닐 수 없습니다.

따라서, 이와 같이 TW State Session을 즉시 재사용하고 싶다면 Application Coding시에 Socket Options에서 SO_REUSEADDR을 사용하거나, Linux Kernel Parameters 중 net.ipv4.tcp_tw_reuse를 활성화(= 1)해주면 됩니다.


결국, 이 Parameter는 TW State Session에 대한 Binding 요청이 발생할 경우 기존 Session을 즉시 소멸시키고 새로운 Binding을 생성하도록 해줍니다.


2MSL(Maximum Segment Lifetime)이라는건 OS에 설정된 패킷(엄밀히 말하면 TCP Segment)이 사라지는 시간으로

1MSL은 2분이기에, 2MSL은 4분이 일반적일 것으로 보입니다.


TIME_WAIT은 당연히 생기는 부분이지만, 서비스/사이트 특성에 따라 비 정상적으로 많이 증가한 경우 영향을 줄 수 있기 때문에

적절한 튜닝이 필요합니다.


* 참고자료

(1) TIME_WAIT 없애기 : http://www.joinc.co.kr/modules/moniwiki/wiki.php/Site/Network_Programing/Documents/Time_Wait

(2) TCP TIME-WAIT State 재사용(reuse), 재활용(recycle)의 차이점 : http://tagnee.tistory.com/22

'Linux > 공통' 카테고리의 다른 글

[Linux] Swap 메모리 초기화 하기  (0) 2014.05.23
[Linux] Vi 명령어 모음  (0) 2014.02.19
하드 링크와 심볼릭 링크  (0) 2014.02.17
Comments