У нас есть, казалось бы, сложная проблема с сетью, с которой я некоторое время боролся, и мне было интересно, есть ли у кого-нибудь какие-либо мысли.
У нас есть несколько серверов, расположенных в AWS London, и еще один набор серверов, расположенных в CoLos в Лондоне и Франкфурте.
Мы подключаемся из AWS к этим CoLos, используя AWS DirectConnect
Серверы AWS в основном подключаются к серверам CoLo с помощью PGSQL, при этом на серверах CoLo размещаются базы данных. Запросы выполняются взад и вперед в течение всего дня.
Серверы CoLo также передают большой объем данных обратно в AWS в форме Rsync и Elastic. Мы никогда не видели никаких проблем с Rsync или Logstash, добавленными в Elastic.
В целом все работает нормально, за исключением того, что время от времени один конкретный тип запроса PGSQL зависает между AWS и CoLo.
Просматривая файлы PCAP, мы видим следующее:
- В течение большей части сеанса сервер (CoLo) отправляет 1460 байт данных, а клиент (AWS) подтверждает эти данные. Это продолжается туда и обратно без проблем
- Затем мы видим, что сервер отправляет обычно от 5 до 20 сегментов, которые не доходят до клиента.Это падение может быть где угодно, поскольку сетевой путь проходит через 2-3 разных оператора связи и DirectConnect.
- Затем клиент правильно начинает ACK до последнего полученного сегмента.
- К тому времени, когда сервер получил ACK, указывающий на потерю пакета, он отправил еще 10-20 сегментов.
- В конце концов сервер начинает повторно отправлять первый пропущенный сегмент, который сразу же принимается и подтверждается ACK.
- Затем сервер отправляет два «текущих» сегмента подряд, но клиент снова подтверждает, что он еще не догнал.
- В этот момент сервер начинает экспоненциальную отсрочку между отправкой «текущего» сегмента и старого сегмента, пока не достигнет 120-секундного промежутка.
- Процесс повторяется следующим образом:
- Сервер отправляет самый последний отсутствующий сегмент
- Клиент сразу подтверждает этот сегмент
- Сервер отправляет два «текущих» сегмента в быстрой последовательности
- Клиент подтверждает их тем же подтверждением, что и на шаге 2.
- Сервер экспоненциально отступает и возвращается к шагу 1 (разрыв увеличивается, пока не достигнет 120 с).
- В конце концов, после достаточно длительного периода (иногда до часа) сервер может повторно отправить все потерянные сегменты и продолжает работать в обычном режиме.
Следует отметить следующее:
- Нигде в захвате не установлен размер нулевого окна, фактически во время восстановления клиент увеличивает свое окно примерно на 6 байт каждый ACK
- Работающий netstat не показывает очереди на прием или передачу во время инцидента.
- Выполнение команды «ss», по-видимому, показывает активацию алгоритма предотвращения перегрузки Cubic.
Очевидно, что любая потеря пакетов не идеальна, но мой вопрос, безусловно, это неправильное поведение, поскольку для восстановления 10-20 потерянных сегментов требуется час?
Очень похоже на нашу проблему: https://engineering.skroutz.gr/blog/uncovering-a-24-year-old-bug-in-the-linux-kernel/ Я мог бы поговорить с хостами наших серверов CoLo и узнать об обновлении ядра.