출처 : IBM 기술정보 사이트

TCP는 UDP와는 달리 connection-oriented protocol인 관계로, 연결을 맺거나 특히 끊을 때,

많은 확인 절차를 거치게 됩니다. 이로 인하여, server와 client 간에 약간의 overhead가 있을

수 있습니다. 특히, web server로 사용되는 system의 경우, 대부분의 client들이 그리 안정적

이지 않은 PC client이므로, connection을 맺던 client application이 crash되는 경우 web serve

r에는 다소간의 문제가 발생할 여지가 있습니다. 가장 대표적인 문제가 FIN_WAIT_2 상태입

니다. 이 상태가 무엇을 뜻하는지, 이로 인해 어떤 문제가 있을 수 있는지, 또 그에

대한 대책은 무엇인지 설명토록 하겠습니다.

TCP socket connection 상태의 종류 

다음은 RFC 793 에 나와있는 그림으로, TCP connection을 맺고 있는 두 system이 정상적으로 connection을 끝내는 과정을 보여줍니다.

TCP A                TCP B
1. ESTABLISHED    ESTABLISHED

2. (Close)
 FIN-WAIT-1 → <SEQ=100><ACK=300><CTL=FIN,ACK>  → CLOSE-WAIT

3. FIN-WAIT-2 ← <SEQ=300><ACK=101><CTL=ACK>  ← CLOSE-WAIT

4. (Close) 
 TIME-WAIT ← <SEQ=300><ACK=101><CTL=FIN,ACK>  ← LAST-ACK

5. TIME-WAIT → <SEQ=101><ACK=301><CTL=ACK>  → CLOSED

6. (2 MSL)   
 CLOSED

Normal Close Sequence

먼저, A가 connection을 close 하면서, 종료 신호인 FIN segment를 A가 B로 보내고, A는 FIN-

WAIT-1 상태로 들어갑니다. 이 상태에서는 A system의 user는 더 이상의 SEND는 사용할 수

없게 되지만, RECEIVE는 계속 가능합니다. B가 그 신호를 받으면 B는 CLOSE-WAIT에 들어가

면서 그에 대한 acknowledge를 보내옵니다. A는 이를 받으면 FIN-WAIT-2 상태가 되고, B는

connection을 close하면서 자신의 FIN을 보냅니다. 이 때 A는 TIME-WAIT 상태가 되어 최종적

으로 B와의 connection이 닫히는지 확인하게 됩니다. 즉, server가 client로부터 FIN에 대한

ACK을 받고나서, client의 FIN을 기다리는 상태가 FIN-WAIT-2 상태입니다. 문제는,

이 FIN-WAIT-2 상태에 대해서는 원래 time-out 값이 정해져 있지 않아서, client가 FIN을 보내

오기 전에 client의 application이나 client 자체가 crash되는 경우, 또는, client program이나

server program에 bug가 있어서 이를 제대로 처리 못하는 경우에는, server에 남아있을

FIN-WAIT-2 상태는 server가 rebooting하기 전에는 끝까지 남아 있게 된다는 것입니다.

이는 netstat -a 명령어로 확인해 볼 수 있는데, 이러한 상태의 connection이 많이 쌓이다보

면 문제를 일으킬 수도 있습니다.

FIN_WAIT_2 에 대한 대책 

가장 좋은 해결책은 bug가 있는 client 또는 server program을 수정하는 것입니다. 대부분의

문제는 그 문제로부터 발생하기 때문입니다. Server에서 운영되는 가장 대표적인 application

은 Apache webserver일 것입니다. Apache는 이 문제에 대한 해결책으로 lingering_close() 함

수 대신 SO_LINGER 함수를 사용하도록 권하기도 합니다. (자세한 것은 아파치 홈페이지

www.apache.org를 참조하시기 바랍니다.) 다른 UNIX들은 FIN-WAIT-2에 대해, time-out 값

을 지정함으로써 이 문제를 회피하도록 해줄 수 있게 해주기도 합니다. Solaris, HP/UX, Linux

등 많은 OS가 이러한 기능을 제공합니다. 이것들은 RFC 793을 위반하는 것입니다만, 필요에

의해 각 vendor가 제공하는 것입니다. AIX는 (다른 UNIX와 마찬가지로) TCP keepalive timer

를 제공함으로써 이 문제를 해결합니다.

# no -a | grep tcp_keep
tcp_keepintvl = 150
tcp_keepidle = 14400

위의 값이 default 값이며, 이 경우, 150 * 500ms clock tick = 75 초, 그리고 14400 * 500ms

clock tick = 2 시간이 됩니다.

keepalive timer는 data segment를 보내면서 reset됩니다. 만약 주어진 tcp_keepidle tick

동안 아무 data segment도 보내지지 않았다면 먼저, 첫번째 keepalive probe packet이 보내

집니다.

이 packet에 대해 reply가 없을 경우, tcp_keepintvl에 정해진 tick만큼을 간격으로 하여, 추가

의 keepalive packet을 보내게 됩니다.

만약 이 keepalive에 대해 reply가 계속 없을 경우, 그 connection은 close됩니다. AIX 4.2에서

는 TCPTV_KEEPCNT (기본값 8)에 해당하는 개수의 probe에 대해 응답이 없을 경우 close되

는데, AIX 4.3에서는 이 no attribute가 없어졌습니다.

tcp_keepinit는 초기 연결시 응답이 없을 경우에 사용되는 값입니다. 따라서, 일단 connection

을 맺고 나서 발생하는 문제에 대해서는 적용되지 않습니다.

위에 따르면, FIN_WAIT_2가 발생하는 경우, default로 2시간 10분 후에야 그 connection이 c

lose되도록 되어 있습니다. 만약, 매우 busy한 web server인 경우에는 이 값들을 조절하는 것

이 필요할 수 있습니다.

참고로 첨부파일을 확인해 주시기 바랍니다.
크리에이티브 커먼즈 라이센스
Creative Commons License
이올린에 북마크하기
Posted by 소리나는연탄.

Leave your greetings here.