Linux Network Internal
많은 양의 트래픽을 처리하는 대용량의 웹 서버에서 흔히 발생하는 timewait와 keepalive 와의 상관관계에 대해 살펴봅니다.
과거 서버의 물리 메모리가 작은 시절에는 시스템 리소스를 차지하는 문제가 있었습니다만, 하드웨어적으로 눈부신 발전이 이루어진 오늘날, timewait 소켓 자체는 문제가 될 만큼 시스템 리소스를 차지하지는 않습니다.
하지만 지금은 timewait를 다른 문제로 볼 필요가 있습니다.
결론부터 말씀드리자면 timewait 가 많다는 것은 서비스의 응답 속도가 느려질 수 있다는 것을 의미합니다.
TCP 3-way handshake 에 대해서는 잘 알고 계실 겁니다.
그렇다면 맺기 만큼 중요한 연결을 끊을 때 사용하는 4-way handshake 도 알고 계신가요?
아래는 4-way handshake 과정입니다.
(참고 : http://kukuta.tistory.com/27)
timewait 소켓은 위 그림에서 보시는 것처럼 먼저 연결을 끊는 쪽에서 생기는 소켓 상태이며, 그 룰에 따라 리눅스에서는 60초의 타이머 작동 후에 커널로 반환되는 룰을 가지고 있습니다.
이 룰은 하드코딩되어 있으며 tw_recycle 파라미터로 변경 가능합니다.
우리가 여기서 주목해야 할 부분은 "먼저 연결을 끊는다"라는 것입니다. 상대방이 더 보낼 데이터가 있는지 없는지 상관하지 않고, 한 번의 통신이 끝나면 "먼저 연결을 끊습니다."
그렇게 되면 어떤 문제가 생길까요? 더 보낼 데이터가 있는 상대는 TCP 연결을 처음부터 다시 해야 하며, 이 과정에서 불필요하게 TCP 3-way handshake 가 한 번 더 발생합니다.
keepalive는 먼저 연결을 끊지 않고, 클라이언트의 연결 요청을 처리한 후 일정 시간 대기하게 됩니다. 이 값을 apache, nginx 의 keepalive timeout 설정으로 변경할 수 있습니다.
이렇게 되면 여러 번의 GET 요청 등이 있을 때 클라이언트는 한 번만 TCP 세션을 연결하고 이 후로는 동일한 세션으로 데이터를 주고받을 수 있게 되기 때문에 불필요한 TCP 세션 연결 비용이 사라지고 더 빠르게 통신할 수 있게 됩니다.
튜닝되지 않은 keepalive 의 사용은 처리 가능한 웹서버 스레드의 부족 현상을 일으킬 수 있습니다. 예를 들어 1000개의 워커가 떠 있는 apache 서버에 1000개의 세션이 keepalive를 켜고 들어오게 되면 1001 번째 세션은 처리를 받아줄 워커가 없기 때문에 웹서버 스레드가 부족해 지고 이는 서비스의 전체적인 응답 속도 저하를 가져올 수 있습니다.
그렇기 때문에 트래픽과 request 기반의 정확한 측정을 통해서 적당한 값의 keepalive timeout 을 설정해 주어야 합니다.
그렇습니다. timewait 소켓이 많다고 무작정 keepalive를 켜는 것도 타임아웃을 일으킬 수 있는 위험한 요소가 될 수 있습니다. 하지만, 튜닝할 수 있고 서비스의 응답 속도를 향상시킬 수 있는 포인트가 있음에도 적용하지 않는 것은 서비스 운영에 도움이 되지 않습니다.
timewait 소켓에 대한 바른 이해와 적정한 값의 keepalive timeout 을 통해 안정적이고 빠른 서비스를 제공할 수 있게 되길 바랍니다.