Каким образом протокол TCP обеспечивает надежную доставку пакетов без потерь?

«Каким образом протокол TCP обеспечивает надежную доставку пакетов без потерь?» — вопрос из категории Сети, который задают на 23% собеседований Devops Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

TCP (Transmission Control Protocol) — это надежный, ориентированный на соединение протокол. Его механизмы гарантируют, что данные будут доставлены получателю в правильном порядке и без ошибок. В инфраструктуре DevOps мы полагаемся на эту надежность для критичных сервисов (БД, брокеры сообщений, API).

Ключевые механизмы TCP:

  1. Установка соединения (Three-Way Handshake): Перед передачей данных клиент и сервер согласуют параметры соединения.

    1. Клиент -> Сервер: SYN (seq=x)
    2. Сервер -> Клиент: SYN-ACK (seq=y, ack=x+1)
    3. Клиент -> Сервер: ACK (seq=x+1, ack=y+1)

    Это гарантирует, что оба конца готовы к обмену.

  2. Секвенсные номера и подтверждения:

    • Каждый отправленный байт имеет порядковый номер (sequence number).
    • Получатель отправляет обратно ACK — номер следующего ожидаемого байта. Например, ACK=1001 означает «я успешно получил все байты до 1000».
    • Это позволяет отслеживать, какие данные дошли, а какие нужно отправить повторно.
  3. Таймауты и повторная передача (Retransmission):

    • Отправитель запускает таймер для каждого отправленного, но не подтверждённого сегмента.
    • Если ACK не пришёл до истечения таймаута (RTO - Retransmission Timeout), сегмент отправляется заново.
    • RTO динамически вычисляется на основе RTT (Round-Trip Time) — времени обмена пакетом и подтверждением.
  4. Контрольная сумма (Checksum): Каждый TCP-сегмент содержит контрольную сумму заголовка и данных. Если получатель обнаруживает несовпадение, пакет молча отбрасывается, что приводит к таймауту и повторной отправке на стороне отправителя.

  5. Управление потоком (Flow Control) с помощью скользящего окна: Получатель сообщает отправителю размер своего приемного буфера в поле window заголовка TCP. Это предотвращает переполнение буфера получателя. Отправитель не может отправить данных больше, чем позволяет это окно.

  6. Управление перегрузкой (Congestion Control): Сложные алгоритмы (Reno, CUBIC) позволяют TCP динамически подстраивать скорость отправки под загруженность сети, избегая коллапса. Основные фазы:

    • Slow Start: Экспоненциальный рост окна перегрузки.
    • Congestion Avoidance: Линейный рост после достижения порога.
    • При обнаружении потерь (по таймауту или дублирующимся ACK) окно резко уменьшается.

Практический взгляд (DevOps):

  • Потери пакетов в сети приводят к росту RTT и повторным передачам, что мы видим в мониторинге (например, Grafana + Prometheus с метриками node_netstat_Tcp_RetransSegs).
  • Высокий процент ретрансмиссий — индикатор проблем с сетью.
  • Настройки ядра Linux (/proc/sys/net/ipv4/tcp_*) позволяют тонко настраивать поведение TCP под конкретную нагрузку (например, для высокоскоростных сетей в дата-центре).

Пример (упрощённо): При отправке HTTP-запроса к API все эти механизмы работают незаметно для приложения, обеспечивая целостность данных.