GN⁺: TCP_NODELAY 옵션의 지속적인 사용
(brooker.co.za)TCP_NODELAY 설정의 중요성
- 분산 시스템에서 지연 시간 문제를 디버깅할 때 가장 먼저 확인해야 할 것은 TCP_NODELAY 옵션의 활성화 여부임
- 많은 분산 시스템 개발자들이 이 간단한 소켓 옵션을 활성화함으로써 지연 시간 문제를 빠르게 해결한 경험이 있음
- 이는 기본 동작이 잘못되었거나 전체 개념이 구식일 수 있음을 시사함
Nagle 알고리즘의 배경과 문제점
- 1984년 John Nagle의 RFC896에서 처음 제안된 Nagle 알고리즘은 TCP 헤더의 비용을 더 잘 상각하여 네트워크에서 더 나은 처리량을 얻는 것이 목적이었음
- Nagle 알고리즘은 이전에 전송된 데이터에 대한 확인 응답이 수신되지 않은 경우 새로운 TCP 세그먼트 전송을 억제하는 방식으로 동작함
- 그러나 이는 지연 ACK(delayed ACK)와 상호작용하여 문제를 일으킴
- Nagle 알고리즘은 ACK가 수신될 때까지 더 많은 데이터 전송을 차단하지만, 지연 ACK는 응답이 준비될 때까지 ACK를 지연시킴
- 이는 패킷을 가득 채우는 데는 좋지만 지연 시간에 민감한 파이프라인 애플리케이션에는 좋지 않음
현대 시스템에서 Nagle 알고리즘의 필요성
- 현대 서버는 수백 마이크로초 안에 엄청난 양의 작업을 수행할 수 있으므로, 단일 RTT에도 데이터 전송을 지연시키는 것이 명확한 이점이 없을 수 있음
- 대부분의 분산 데이터베이스와 시스템은 단일 바이트 패킷을 보내지 않음
- 이는 전송할 데이터가 더 많고, TLS와 같은 프로토콜의 오버헤드와 인코딩 및 직렬화 오버헤드 때문임
- 작은 메시지를 보내지 않는 것은 여전히 중요하지만, 이는 애플리케이션 계층에서 효과적으로 처리되고 있음
TCP_NODELAY 사용에 대한 의견
- 지연 시간에 민감한 분산 시스템을 구축할 때는 걱정 없이 TCP_NODELAY를 활성화(Nagle 알고리즘 비활성화)해도 됨
- 현대 시스템에서는 트래픽 및 애플리케이션 mix, 하드웨어 성능을 고려할 때 Nagle 알고리즘이 필요하지 않을 수 있음
- 즉, TCP_NODELAY가 기본값이 되어야 함
- 이는 일부 "모든 바이트 쓰기" 코드를 느리게 만들 수 있지만, 효율성을 중요하게 여긴다면 어차피 해당 애플리케이션을 수정해야 함
GN⁺의 의견
-
Nagle 알고리즘과 delayed ACK 간의 상호작용 문제는 프로토콜 설계가 얼마나 어려운지를 보여주는 좋은 사례임. 두 가지 합리적인 기능이 의도치 않은 동작을 만들어내는 상황은 시스템 설계자에게 익숙할 것임.
-
애플리케이션 계층에서 작은 메시지 전송을 최적화하는 것이 일반적인 추세임. 효율적인 인코딩과 직렬화를 통해 불필요한 오버헤드를 최소화하는 것이 중요함.
-
Nagle 알고리즘의 목적이 네트워크 대역폭 최적화였다면, 오늘날에는 지연 시간 최소화가 더 중요한 요구사항임. 애플리케이션의 응답성이 사용자 경험에 직결되는 상황에서 불필요한 지연은 피해야 함.
-
다만 TCP_NODELAY를 기본으로 하는 것이 모든 상황에 이상적인 것은 아닐 수 있음. 대역폭이 제한적인 환경이나, 전송 효율성이 지연시간보다 훨씬 중요한 시스템의 경우 선별적으로 Nagle 알고리즘을 활용할 필요가 있음.
-
네트워크 프로토콜 설계 시 다양한 요구사항 간의 균형을 맞추는 것이 중요함. 범용 프로토콜의 기본 동작을 바꾸는 것은 신중할 필요가 있지만, 애플리케이션의 요구에 맞게 적절한 옵션을 선택하는 유연성도 필요할 것으로 보임.
Hacker News 의견
요약:
- Nagle의 알고리즘은 배치 쓰기를 시도한 것으로, 하드웨어나 네트워크, 애플리케이션, 사용 사례에 상관없이 배치 쓰기가 더 나은 경우가 있음
- 오늘날의 많은 컴퓨팅은 배치 쓰기를 사용하며, QUIC와 같은 새로운 고수준 프로토콜도 쓰기 배치를 수행하여 TCP의 독립적인 연결 및 오류 처리를 사용자 공간으로 이동시킴
- 네트워크가 포화 상태가 되면, Nagle의 알고리즘은 QUIC 수정의 형태로 애플리케이션 코드에서 더 깊이 반환될 것임
- Nagle의 알고리즘은 작은 패킷으로 인해 초당 패킷(PPS)이 포화 상태가 되는 경우에도 유용함
- Nagle의 알고리즘은 일부 워크로드에는 잘 작동하지 않으므로, 엔지니어가 소켓을 만들 때 강제로 설정해야 하는 것이 좋음
- TCP_QUICKACK 소켓 옵션이나
/proc/sys/net/ipv4/tcp_delack_min
및/proc/sys/net/ipv4/tcp_ato_min
을 사용하여 지연 ACK를 비활성화할 수 있음 - 대역폭이 제한된 세상에서 TCP 패킷을 모든 바이트에 대해 보내는 것은 대역폭을 낭비하므로, Nagle의 알고리즘이 필요함
- 애플리케이션 소스에 액세스할 수 없는 경우 TCP_NODELAY를 활성화하는 좋은 방법은 아직 없음
- Go와 같은 최신 언어는 기본적으로 TCP_NODELAY를 활성화하므로 이 문제가 발생하지 않음
- 애플리케이션이 TCP 스택에게 대화형 쉘이라는 것을 알려줄 수 있는 방법이 있다면, TCP_NODELAY를 기본적으로 꺼두고 해당 애플리케이션에 대해서만 켤 수 있어 오버헤드를 줄일 수 있음