brunch

You can make anything
by writing

C.S.Lewis

by 강진우 Jul 10. 2015

tcp_tw_reuse와 tcp_tw_recycle

Linux Network Internal

시스템 엔지니어에게 가장 골치 아픈 커널 파라미터가 뭐냐고 묻는다면 아마 위 두 값이라고 하시는 분들이 많으실 겁니다. 비슷하게 보이지만 차이점을 알기가 힘든 두 값에 대해 간단한 테스트를 통해 그 의미를 알아보는 시간을 마련해 보았습니다.


준비물

우선 두 대의 서버를  준비합니다. 편의상 client,  server라고 지정합니다.

그리고  client에서는 net.ipv4.ip_local_port_range  값을 default 값에서 32768 32768로 고칩니다. 

server에서는  nginx를  yum으로 기본 설치해서 80만 띄워 놓습니다.


tcp_tw_reuse

먼저 tcp_tw_reuse 에 대해  살펴보겠습니다.

client에서  server로 curl 명령으로 페이지를 가져오면 방금 사용했던 포트는 timewait 상태로 빠지게 됩니다. 그리고 곧바로 curl 명령을 다시 입력하면 아래와 같이 에러가  발생합니다.

네.. 당연하겠죠? 사용할 수 있는 로컬 포트는 32768  하나뿐인데 TW 상태이니 결국 사용할 수 있는 로컬 포트가 하나도 없는 상태가 됩니다. 

자.. 그럼  tw_reuse를 enable 하면 어떻게 변하게 될까요?

보이는 것처럼 몇 번이고 TW 상태의 소켓을 재사용하게 됩니다. 

tw_reuse는 outgoing 트래픽에 대해 로컬 포트가 모자랄 경우, TW 상태에 있는 소켓을  재사용할 수 있게 해 줍니다. 

그래서 로컬 포트가 고갈되는 현상이 있을 경우 ip_local_port_range 값을 튜닝해 주기 보다는  tw_reuse를 사용하는 것이 좋습니다.

일부 인터넷에 있는 문서들 중에는 tw_reuse 가 SO_REUSEADDR와 같은 역할을 한다고 하는데, 잘못된  정보입니다. SO_REUSEADDR 은  bind와 listen 하는 과정에서 커널이 선점하고 있는 포트를 다시 사용할 수 있게 해 주는 것이고  tw_reuse는 outgoing 트래픽에 대해 TW 상태의 로컬 포트를 재사용할 수 있게 해 주는  것입니다.

자세한 내용은 http://docs.likejazz.com/time-wait/ 이 곳을  참고하시면 됩니다. 아주 정리가 잘 되어 있는  블로그입니다.

tcp_tw_recycle

이번엔 tcp_tw_recycle 에 대해  살펴봅니다. tcp_tw_recycle 은  server에서  살펴봅니다.

client에서  telnet으로 붙은 후에 GET 요청을 보내 보면,  server에서는 연결을 끊기 때문에  (keepalive는 꺼 둡니다.) 사용했던 소켓이 TW 상태로 빠집니다.

이 상태에서 client 가 다시 한 번 GET 요청을 하게 되면 어떻게 될까요? 

네.. 바로바로 재사용이 됩니다. 어라..? 안될 거라고 생각했는데..? server 입장에서는 172.16.33.136:32768 포트는 끊어진 상태로 간주되기 때문에 동일한 IP에서 동일한 포트로 다시 한 번 연결 요청이 온다면 거절할 이유가 없습니다. 그래서 server 입장에서는 tw_recycle 값에  관계없이 TW 소켓을 재사용하게 됩니다.

그렇다면  tw_recycle을 enable 하면 동작이 어떻게 변화할까요?

몇 번을 요청하더라도  netstat으로 소켓이 보이지 않을 만큼 빠르게 TW 소켓이  정리됩니다. 마치 아예 만들어지지 않는 것처럼 요. 이 부분을 좀 더 자세히 살펴보기 위해 커널 소스 코드를 잠깐 봅시다.

아주 중요한 힌트가 net/ipv4/tcp_minisock.c 에 있습니다.

tw_recycle이 켜져 있으면 tw_timeout 의 값이 rto 값으로 변경되기 때문에 TW 상태의 소켓 유지 시간이 아주  짧아집니다. 

특히 내부 서버간 통신의 경우 rto 가 매우 짧기 때문에 TW 소켓이 눈에 보이지도 않을 정도의 속도로 정리가 됩니다.

켜져 있지 않으면 TCP_TIMEWAIT_LEN 값에 따라 하드 코딩된 60초로 설정이 됩니다.

또한 tcp_tw_recycle 이 켜져 있으면 TW 상태의 소켓을 재사용할 때 timestamp 값을 비교하는 로직이 추가되는데, 바로 이 로직 때문에 패킷 드랍이 발생할 수 있습니다.

NAT 기반의 클라이언트들이 tw_recycle 이 켜져 있는 서버에 접속할 경우, NAT 의  IP와 포트가 똑같은 순간이 발생할 텐데요, NAT 뒷 단에 있는 클라이언트들은 서로 다른  timestamp를 가지기 때문에 첫 번째 클라이언트를 제외한 나머지 클라이언트들에서 패킷 드랍이 발생하게 됩니다.


결론

여기까지 간단한 테스트를 통해 두 파라미터가 서버의 동작에 어떻게 영향을 끼치는 지  살펴봤습니다.

결론을  얘기하자면..

tcp_tw_reuse는 enable
tcp_tw_recycle은 disable


이상입니다. 제가 정리한 내용 중에 잘못된 내용이 있으면 언제든지 말씀해 주세요~

브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari