Позвольте мне сразу заявить, что я знаю о сетях на этом уровне достаточно, чтобы быть опасным, поэтому, если я скажу что-нибудь глупое, пожалуйста, будьте добры.
Я использую балансировщик нагрузки Big IP перед 3 серверами Apache. Все 3 сервера Apache находятся на одной физической машине (под управлением Linux), привязаны к порту 80 на 3 разных виртуальных IP-адресах, но я не думаю, что это играет роль в этой проблеме. У нас есть LB, настроенный так, что один и тот же клиент каждый раз получает один и тот же WEB-сервер, управляемый с помощью файла cookie, предоставленного LB.
Если я прохожу через LB для доступа к нашему приложению, я иногда (в 5-15% случаев) получаю страницу, на которой браузер просто вращается, не возвращаясь. Если я попаду на каждый из веб-серверов напрямую, я никогда этого не получу. Используя WireShark, я посмотрел, что происходит на моем ПК, LB и WEB-сервере, на который я обращался через LB, и увидел следующее:
1) В большинстве случаев порт, который ПК использовал для обращения к LB, был портом, который LB использовал для обращения к WEB-серверу, что я считал «нормальным»; все 3 раза я повторял свою проблему, порты были разными (например, 1234 между ПК / LB и 2345 между LB / WEB). Но не всегда, когда они были разными, я видел проблему. Это может быть отвлекающим маневром ....
2) Связь ПК <-> LB осуществляется с пакетами длиной 1260 байт; Пакеты LB -> WEB имеют размер 1260 байтов, но пакеты LB <- WEB несколько кратны 1260. Когда WEB отправляет 2520 байтов на LB, LB получает его в пакетах 2x1260 байтов и отправляет только один ACK. Затем он отправляет обратно на ПК пакетов размером 2 x 1260 байтов и получает один ACK от ПК. Я не понимаю, почему 2520 разбит на 2x1260, и я не понимаю, почему ПК знает, что нужно отправлять только один ACK. Это тоже может быть отвлекающим маневром ....
3) В какой-то момент WEB-сервер отправляет данные на LB, для которого он не получает ACK, а затем повторно отправляет пакет, который начал эту последовательность данных. Однако я не знаю, почему происходит повторная передача, поскольку прошло всего 0,6 секунды, поэтому не может быть, что истекло время ожидания (ну, я полагаю, это может быть, но это кажется маловероятным). Кроме того, исходный пакет WEB -> LB был 5040 байтов (4x1260), но повторная передача составляет только 1260. LB получил все 4 пакета из исходной отправки 5040, но никогда не отправлял ACK по какой-либо причине. Я видел и другие случаи, когда LB мог обработать 5040 байтов, отправляемых ему, что он признавал очень хорошо, поэтому не похоже, что длина отправленного пакета является проблемой. Однако ни один из этих пакетов не был отправлен с LB обратно на ПК.
4) Однако из WEB в LB повторно отправляется только первый блок данных 1260. Есть небольшая задержка (0,4 секунды), а затем происходит вторая повторная передача данных, начиная с первого фрагмента 1260, но на этот раз повторно отправляются все пакеты 4x1260. Однако ACK, отправленный обратно LB, предназначен для всех 5 повторно отправленных пакетов, даже если один из них явно был повторно отправлен дважды (я основываю это на относительном номере последовательности, показанном WireShark; отправленный обратно ACK равен seq номер первого повторно отправленного пакета + 5x1260, даже если порядковый номер второго повторно отправленного пакета такой же, как и у первого повторно отправленного пакета). Это действительно плохо.
5) Хуже всего, я думаю, то, что порты перепутались. Исходные порты разговора следующие:
PC <-> LB == 2723
LB <-> WEB == 2722
К этому разговору примешивается еще один, похожий на это:
PC <-> LB == 2722
LB <-> WEB == 2723
Этого было достаточно, чтобы вызвать у меня косоглазие, но я убедился, что разговоры происходили на тех портах, которые, как я думал, были, на основе содержимого пакетов (тьфу). Второй диалог завершается успешно (фактически, на этом наборе портов есть два диалога, оба из которых завершаются успешно). После отправки первого (прерванного?) Пакета повторной передачи, но до отправки второго набора повторных передач 4х1260, происходит диалог:
PC <-> LB == 2722
LB <-> WEB == 2722
Итак, исходный диалог LB <-> WEB на порту 2722 прерван. Я не думал, что это разрешено протоколом. На этот порт не отправляются сигналы FIN или SYN в любом направлении. Порядковый номер, отправленный из LB -> WEB для этого недавно начатого разговора, - это то, что я ожидал. ACK из WEB в LB имеет правильный порядковый номер, но ACK выключен (ровно на 1260).
Этот второй диалог, кажется, никогда не происходит, поскольку после повторной передачи 4x1260 WEB отправляет еще один, новый, 1260 фрагмент данных, и все это является ответом на исходный запрос (определяемый путем изучения данных в пакетах. ). Затем LB отправляет обратно ACK, и это то, что я ожидал от исходного разговора (последний ACK + 4x1260 + 1260).
Итак, у меня есть подсказки относительно того, что происходит, но я не знаю, почему это могло произойти, и уж точно не знаю, как это исправить. Куда мне идти дальше?
РЕДАКТИРОВАТЬ: Я только что кое-что вспомнил; во время повторной отправки 4x1260 из WEB в LB LB отправляет обратно ACK, который ровно на 100 байт больше, чем я ожидал. Однако после того, как первый пакет 1260 новых данных отправлен, LB отправляет обратно ACK, который в точности соответствует тому, что должен быть (т.е. он исправился сам). Я понятия не имею, как это могло произойти, что это означает, и даже если это имеет смысл.
Порт tcp будет меняться по мере необходимости на клиенте и на стороне сервера BIG-IP, который теперь является клиентом веб-сервера. Это ожидаемое поведение, поскольку BIG-IP обрабатывает полностью отдельное TCP-соединение с клиентом и с сервером.
Поскольку прокси-сервер обрабатывает отдельные соединения между клиентом и сервером, обычное поведение TCP будет действовать по-разному на стороне клиента и на стороне сервера соединения. Какой профиль TCP вы применяете и к какой стороне прокси-сервера (вы можете применять разные профили для клиентской и серверной стороны соединения или одинаковые для обоих, на ваше усмотрение, в зависимости от ваших вариантов использования и сетевых сред) изменит, какие данные на самом деле на проводе, в какое время, сколько и как часто отправляются подтверждения.
повторные передачи являются обычным явлением, и то, как стек TCP обрабатывает перегрузку сети, зависит от установленного стека, как на стороне клиента, так и на стороне сервера соединения. Опять же, у вас есть два клиента и два сервера для любого сценария клиент-> BIG-IP-> сервер.
потребуется просмотреть весь захват, чтобы диагностировать наблюдаемое вами поведение.
не думайте, что порт TCP вызывает здесь беспокойство.
Без подробностей, я предполагаю, что у вас был включен стандартный профиль tcp вместо настраиваемого профиля, и он плохо себя вел с вашим приложением. Я настоятельно рекомендую использовать настраиваемые профили и привлечь кого-нибудь, кто знает, как работают алгоритмы TCP-потока и управления перегрузкой, и какие настройки в профиле TCP плохо работают с определенными приложениями. Несколько лет назад мы написали серию из 10 частей о профиле BIG-IP TCP (можно было бы использовать обновление со всеми изменениями с тех пор, но это все еще хороший источник информации), которая, я думаю, поможет: https://devcentral.f5.com/articles/investigating-the-ltm-tcp-profile-nagles-algorithm
Меня особенно бросает в глаза то, что ваши веб-серверы находятся на одном компьютере с разными IP-адресами. Вы действительно ничего не получите от балансировки нагрузки, если поместите все серверы в один ящик.
Кое-что из того, что вы описываете с помощью пакетов, кажется нормальным; Вы использовали функции «Экспертная информация» и «Следуй за TCP-потоком» в Wireshark? Они будут отображать высокоуровневые представления TCP-соединений. Также имейте в виду, что Wireshark может не захватывать все пакеты (особенно, если вы используете гигабитный Ethernet).
Что касается проблемы, возможно, вы видите ошибку в LB, обнаруженную тем фактом, что все ваши веб-службы находятся в одном окне, что означает, что все ваши три IP-адреса имеют одинаковый MAC-адрес. Если LB отслеживает соединения с использованием MAC-адреса, это может сбивать с толку три IP-адреса ваших серверов и направлять пакеты не в то место.