- NetworkManager가 잠깐의 연결 불안정을 “네트워크 없음”으로 판단하듯, 일부 소프트웨어는 TCP 복구보다 자기 상태 판단을 더 신뢰하지만 실제 네트워크에서는 위험할 수 있음
- “보낸 데이터는 도착한다”, “양쪽은 결국 전달된 바이트에 합의한다”, “HTTP나 SMTP 같은 애플리케이션 프로토콜로 보장할 수 있다”는 믿음은 일부 상황에서 깨짐
- ACK 처리 중 연결이 끊기면 송신자는 세그먼트 수신 여부를 알 수 없고, 이 한계는 Two Generals’ Problem처럼 단일 2자 TCP 스트림만으로 해결되지 않음
- SMTP도 RFC 1047과 RFC 2821에서 이 문제를 다루며, 전달 책임이 넘어가는 순간에는 연결 실패 시 중복 전송이나 누락이 생길 수 있는 애매한 구간이 있음
- 이상한 네트워크를 예외로 치거나 Nagle 알고리듬, 혼잡 제어, ICMP 차단 같은 세부 동작을 무시하면 실제 장애를 잘못 해석하기 쉬움
TCP보다 먼저 네트워크 상태를 단정하는 문제
- NetworkManager를 쓰던 사용자는 과거 기숙사와 캠퍼스 로밍 환경에서 무선 연결 불안정을 겪었고, 패킷 손실이 조금만 있어도 시스템 전체에 “네트워크 없음”이 전달되는 상황을 경험함
- 당시 네트워크는 곧 돌아올 가능성이 있었고, 일반적인 TCP 복구가 지연 시간 급증을 동반하더라도 애플리케이션에는 투명하게 보일 수 있었음
- 이 사례는 TCP가 처리할 수 있는 일시적 장애를 애플리케이션이나 시스템 컴포넌트가 너무 빨리 실패로 해석하는 문제와 이어짐
TCP에 대해 흔히 틀리는 믿음
- 다음 문장들은 TCP를 다룰 때 자주 나오는 믿음이지만, 각각 적어도 어떤 경우에는 거짓임
- TCP는 신뢰 가능하므로 보낸 모든 데이터가 상대에게 도착함
- TCP는 대체로 신뢰 가능함
- TCP가 완전한 의미의 신뢰성을 제공하지 않더라도, 송신자와 수신자는 결국 어떤 바이트가 전송됐는지 정확히 합의함
- HTTP나 SMTP 같은 메시지 지향 애플리케이션 프로토콜을 TCP 위에 만들면 그런 보장을 만들 수 있음
- TCP 패킷이라는 것이 있음
- TCP 패킷이라는 것은 없음
- 잘 알려진 원격 호스트에 연결하지 못하면 오프라인임
- Nagle 알고리듬은 좋음
- Nagle 알고리듬은 나쁨
- Nagle 알고리듬을 신경 쓸 필요가 없음
- TCP는 네트워크를 지나는 양방향 Unix pipe처럼 생각해도 충분함
- 네트워크가 TCP에 투명하면 IP에도 투명함
- 네트워크가 HTTP/1.1에 투명하면 TCP에도 투명함
- 표준 프로토콜에 투명하지 않은 이상한 네트워크는 예외적이라 무시해도 됨
- TCP는 IP 위에 구현됨
전달된 바이트를 정확히 합의하기 어려운 이유
- TCP 신뢰성과 관련된 앞의 1~4번 문제는 Two Generals’ Problem과 연결됨
- ACK가 아직 처리 중인 상태에서 연결이 끊기면, 송신자는 해당 세그먼트가 수신됐는지 확인할 방법이 없음
- 이 한계는 TCP 위에 복잡한 계층을 더 쌓아도 사라지지 않음
- 단일 2자 TCP 스트림 위에서는 이 보장을 만들 수 없고, 그런 보장에는 Paxos나 Raft와 유사한 방식 및 최소 3개 노드가 필요함
- 같은 종류의 문제는 TCP뿐 아니라 UDP나 IP 기반의 2자 서비스에도 적용됨
SMTP가 드러내는 전달 책임의 회색 지대
- SMTP는 양쪽이 메시지 수신 여부를 명시적으로 신경 써야 하는 서비스라 이 문제가 잘 드러남
- RFC 1047은 SMTP 관점에서 이 문제를 다루고, RFC 2821은 구현이 RFC 1047의 핵심 조언을 따라야 한다고 정함
- SMTP 예시에서는 다음 상태들이 구분됨
- 클라이언트에서 서버로 이메일이 전송됐다고 양쪽이 합의하는 지점에 도달할 수 있음
- 서버가 이메일 전달 책임을 맡았다고 양쪽이 합의하는 지점에도 도달할 수 있음
- 하지만 그 전에 누가 현재 이메일 전달 책임을 지는지 애매한 상태를 반드시 지나야 함
- 이 애매한 상태에서 연결이 끊기면 이메일을 중복하거나 누락하게 됨
- SMTP 명세는 이메일을 중복하는 쪽을 지정하지만, 실제 구현에서 어느 정도 테스트됐는지는 알 수 없음
- Paxos와 Raft의 목적은 최종 상태 자체를 달성하는 것보다, 이런 애매한 상태를 방지하는 데 있음
2자 합의에서 남는 지식의 한계
- 한 댓글은 불신뢰하지만 악의적이지 않은 링크에서도 두 당사자가 일부 바이트 집합에 대해 “전달됐고 양쪽 모두 그 사실을 안다”고 합의할 수 있다고 봄
- 보충 논의에서는 한 당사자가 합의 집합에 최소한 처음 N바이트가 포함된다는 사실은 알 수 있지만, 합의 집합이 정확히 처음 N바이트라고 알 수는 없다고 정리함
- 따라서 “확실히 전달됐고 양쪽이 안다”는 바이트 집합은 존재할 수 있어도, 그 뒤에는 송신자와 수신자가 서로의 지식 상태를 확정할 수 없는 회색 지대가 남음
- 이 차이를 놓치면 분산 시스템에서 이상한 실패가 발생하기 쉬움
현실 네트워크와 하위 계층의 함정
- “표준 프로토콜에 투명하지 않은 이상한 네트워크는 무시해도 된다”는 믿음은 여러 번 문제를 일으킴
- buffer bloat는 라우터가 혼잡 제어 메커니즘을 깨뜨리는 사례로 다뤄짐
- ICMP를 차단하거나 이해하지 못하는 트래픽을 떨어뜨리는 네트워크도 문제가 될 수 있음
- “혼잡 제어를 알 필요가 없다”는 믿음 역시 TCP를 잘못 이해한 사례에 가까움
- 하위 예로 “원하는 속도가 나오지 않으면 TCP 연결을 여러 개 열면 된다”는 생각이 나옴