Как настроить TCP для высокочастотных соединений между двумя узлами

Я чесал в затылке последние несколько дней, пытаясь найти с решением следующей проблемы:

В нашем центре обработки данных у нас есть F5, работающий на оборудовании BigIP, который действует как единая точка входа для запросов HTTPS от клиентских машин в различных офисах по всей стране. F5 прерывает TLS, а затем перенаправляет все запросы на два балансировщика нагрузки Traefik, которые направляют запросы на различные экземпляры службы (узлы Traefik работают в Docker в Red Hat Enterprise, но я считаю, что это не имеет отношения к моей проблеме). С точки зрения пропускной способности, ЦП и памяти, эти три сетевых компонента более чем способны обрабатывать объем запросов и трафика с достаточной емкостью.

Однако мы заметили частые задержки в 1000 мс в запросах HTTP (S). что делают клиенты, особенно во время высокой нагрузки. Мы отследили проблему до следующей основной причины:

  • Во время высокой нагрузки «клиент» F5 инициирует новые TCP-соединения с «серверными» узлами Traefik с высокой частотой (возможно, более 100 в секунду).
  • Эти соединения разрываются на «стороне сервера» Traefik после получения ответов HTTP.
  • Каждое закрытое соединение остается в состоянии TIME_WAIT в течение 60 секунд на хосте Traefik.
  • Когда F5 инициирует новое соединение, оно случайным образом выбирает доступный порт из временного диапазона портов.
  • Иногда (часто во время высокой нагрузки) в Traefik уже есть соединение в состоянии TIME_WAIT с тем же исходным IP + портом,IP-адрес назначения + комбинация порта. Когда это происходит, стек TCP (?) На хосте Traefik игнорирует первый пакет SYN. Примечание: RFC 6056 называет это конфликтом идентификаторов экземпляров .
  • Через 1000 мс срабатывает механизм тайм-аута повторной передачи (RTO) на F5 и повторно отправляет SYN-пакет. На этот раз хост Traefik принимает соединение и правильно завершает запрос.

Очевидно, что такие задержки в 1000 мс абсолютно неприемлемы. Итак, мы рассмотрели следующие решения:

  1. Уменьшите RTO в F5, чтобы ретранслировать быстрее, например до 200 мс.
  2. Уменьшите net.ipv4.tcp_fin_timeout, чтобы быстрее закрыть прерванные TIME_WAIT соединения.
    Обновление: Это применимо только к соединениям, которые были прерваны другой стороной, когда нет FIN возвращается. Это не влияет на соединения в состоянии TIME_WAIT.
  3. Включить net.ipv4.tcp_tw_reuse: бесполезно для входящих соединений.
  4. Включить net.ipv4.tcp_tw_recycle: AFAIK противопоказан, если клиент отправляет случайные метки времени TCP. Противоречивая информация (включая эмпирические данные), была ли эта функция удалена из Linux или нет. Кроме того, обычно рекомендуется НЕ связываться с.
  5. Добавьте больше исходных IP-адресов и / или заставьте Traefik прослушивать несколько портов, чтобы увеличить количество перестановок в кортежах IP / портов.

Я откажусь от №1, потому что это всего лишь диапазон - сказал. Задержки по-прежнему случаются, но они менее заметны. №3 все равно не будет иметь никакого эффекта, №4, скорее всего, сделает систему нефункциональной. Остается №2 и №5.

Но исходя из того, что я узнал после прочтения десятков сообщений и технических статей, оба они в конечном итоге только уменьшат вероятность того, что «коллизии». Потому что то, что в конечном итоге мешает отправляющей стороне, F5, (псевдо) случайным образом выбрать комбинацию эфемерного порта, исходного IP-адреса и целевого порта, которая все еще существует в состоянии TIME_WAIT на целевом хосте Traefik, независимо от того, насколько коротка настройка fin_timeout (которая все равно должен оставаться в многосекундном диапазоне)? Мы бы только уменьшили вероятность коллизий, но не исключали их.

После всех моих исследований и во времена гигантских веб-приложений меня действительно удивляет, что эта проблема больше не обсуждается в сети (и нет доступных решений). Я был бы очень признателен за ваши мысли и идеи о том, есть ли лучшее, более систематическое решение в области TCP, которое снизит количество коллизий до нуля. Я думаю о конфигурации TCP, которая позволит хосту Traefik немедленно принять новое соединение, несмотря на то, что старое соединение находится в состоянии TIME_WAIT. Но на данный момент это не удалось найти.

Случайные мысли и моменты:

  • На данный момент невозможно изменить наши различные внутренние приложения для использования более длительно работающих HTTP (S) соединений, чтобы уменьшить количество запросов / соединений в секунду.
  • Сетевая архитектура F5 и Traefik не подлежит обсуждению, не может быть изменена.
  • Недавно я исследовал выбор временного порта на клиентах Windows. Этот алгоритм кажется последовательным, а не случайным. Максимально увеличивает время до повторного использования порта, снижает безопасность.
  • Во время нагрузочных тестов в системе, которая в противном случае не работала, мы генерировали ~ 100 HTTP-запросов / соединений в секунду. Первые конфликты произошли уже через несколько секунд (скажем, до 2000 запросов), даже если F5 настроен на использование более 60 КБ эфемерных портов. Я предполагаю, что это связано с псевдослучайным характером алгоритма выбора порта, который, похоже, плохо справляется с предотвращением конфликтов идентификаторов экземпляров.
  • Тот факт, что хост Traefik принимает TCP-соединение при повторной передаче пакета SYN, является возможно, это функция реализации TCP. RFC6056 говорит об убийстве TIME_WAIT , которое может быть связано с этим.

Обновление : Согласно Звездный эксперимент , настройка net.ipv4.tcp_fin_timeout НЕ влияет на TIME_WAIT состояние, только состояние FIN_WAIT_2. И согласно Самиру Джафферали , в системах Linux (включая нашу Red Hat Linux) период TIME_WAIT жестко запрограммирован в исходном коде и не может быть настроен. Согласно источнику, на BSD это можно настроить, но я не проверял это.

8
задан 22 November 2019 в 10:37
3 ответа

В нашем дата-центре у нас есть работа F5 аппаратных средств BigIP, которые действуют как [1 110] единственный входная точка для Запросов HTTPS от клиентских машин в наших различных местоположениях станции по всей стране .

, Если эта единственная точка (фронтенд) остается одинокой, когда это передает соединения с бэкендом, почему Вы задаетесь вопросом об отклонениях? Особенно, если интенсивность соединений "возможно 100 + в секунду".

Ваша установка в основном сжимает набор того с более высокой кардинальностью в другой с кардинальностью значительно ниже.

в конечном счете только уменьшают шанс тех "коллизий"

, Это помещается в основание того, как работают сети с коммутацией пакетов. Скажите, на уровне Ethernet также существуют коллизии. Случайность неизбежна, и TCP/IP имеет дело с нею. Сам протокол IP был создан не с LAN в памяти, на самом деле (но все еще работает отлично там также).

Так да, "Добавляют больше исходного дюйм/с и/или заставляют Traefik послушать на нескольких портах", довольно разумный способ следовать.

4
ответ дан 2 December 2019 в 23:00

Хотя я также думаю, добавляя, что больше IP-адресов является самым простым путем вперед, Вы рассмотрели исследование, снова использующее соединения TCP между F5 и узлами Traefik вместо того, чтобы создать новый на внешний запрос?

я не уверен, как поддержки F5, что, но возможно это столь же просто как переключающийся на http2 между F5 и узлами Traefik. См. https://developers.google.com/web/fundamentals/performance/http2#one_connection_per_origin

3
ответ дан 2 December 2019 в 23:00

Повороты там были очень простое решение этой проблемы, в конце концов, которую мы выяснили после работы с поставщиком Traefik некоторое время. Оказывается также, что то, что мы выполняем Traefik в Докере , делает вопрос. Проблема и решение очень характерны для нашей установки, но я все еще хочу зарегистрировать здесь его в случае, если другие должны встретиться с тем же. Тем не менее, это делает не , делают недействительным другой, более общие рекомендации, поскольку коллизии идентификаторов экземпляра являются настоящей проблемой.

короткая история Long: Все экземпляры Traefik настроены как ограниченные хостом контейнеры (т.е. связаны с определенными хостами), работающий в кластере Роя Докера. Экземпляры Traefik должны выставить порт на уровне хоста так, чтобы они стали достижимыми от F5, который, очевидно, не является участником Роя Докера. Те выставленные порты были настроены в вход режим, который не был только ненужным (никакая потребность направить трафик через входную сеть Роя Докера), но был также причиной для отбрасывания/игнорирования пакетов SYN. После того как мы переключили режим порта на хост , задержки исчезли.

Прежде:

  ports:
  - target: 8080
    published: 8080
    protocol: tcp
    mode: ingress

После:

  ports:
  - target: 8080
    published: 8080
    protocol: tcp
    mode: host
2
ответ дан 2 December 2019 в 23:00

Теги

Похожие вопросы