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를 기본적으로 꺼두고 해당 애플리케이션에 대해서만 켤 수 있어 오버헤드를 줄일 수 있음