Клиент отправляет на сервер FIN ACK с задержкой (~ 500 мс)

У меня есть клиент node.js (10.177.62.7), запрашивающий некоторые данные из службы http rest с сервера (10.177.0.1). Клиент просто использует метод node.js http.request() (agent=false). Клиент находится на коробке Ubuntu 11.10.

Почему клиент отправляет FIN ACK через 475 мс? Почему так медленно? Он должен немедленно отправить FIN ACK. У меня много таких ситуаций. Около 1% всего трафика приходится на запросы с отложенным FIN ACK.

Простой ЦП на клиенте составляет около 99%, поэтому ничто не истощает ЦП.

Как это отладить? Что бы это могло быть? Есть ли какая-либо опция sysctl, которую мне нужно настроить?

На снимке экрана 2-й столбец — это время, прошедшее между пакетами.

Ссылка на увеличенное изображение.

введите здесь описание изображения


person Tereska    schedule 29.07.2012    source источник
comment
Я удалил свой ответ об активности HTTP, поскольку он был окончательно исключен. Хотя других ответов и не придумаешь. FIN должен погаснуть, как только сокет будет закрыт.   -  person Alan Curry    schedule 30.07.2012
comment
@AlanCurry Но FIN/ACK будет отправлен только тогда, когда клиент прочитает входящий FIN и решит закрыть сокет, что может занять любое время. Это поведение node.js, а не стека TCP/IP.   -  person user207421    schedule 30.07.2012
comment
Конечно, но если он находится в середине вызова клиентской библиотеки http, он не выполняет поддержку активности, а загрузка ЦП составляет 1%, почему так долго закрывается сокет после чтения EOF?   -  person Alan Curry    schedule 30.07.2012
comment
Сколько одновременных подключений? Сколько всего подключений вы генерируете? Насколько велик запрашиваемый объект? Какова сетевая задержка между клиентом и сервером? Насколько велик ваш объект POST? Сколько из них происходит одновременно? Реализуете ли вы какую-либо отсрочку в своем клиенте, когда возникают ошибки при подключении?   -  person jxh    schedule 07.08.2012
comment
Есть около 1000 сим подключений. Объект запроса очень маленький (около 150 байт), задержка 2-3 мс. Пост около 1-20кб. Логики отката нет.   -  person Tereska    schedule 07.08.2012
comment
@Tereska: Возможно, вы сожгли все свои эфемерные порты и ждете истечения тайм-аута 2xMSL для некоторых из них, прежде чем можно будет создавать новые подключения. Вы проверяли нетстат?   -  person jxh    schedule 11.08.2012
comment
Мой sysctl настроен на это. У меня диапазон портов начинается с 1024, time_wait 1 с. netstat показывает около 1 тыс. установленных соединений и пару в time_wait.   -  person Tereska    schedule 11.08.2012


Ответы (1)


Такое поведение связано с функцией отложенного подтверждения в стеке TCP RFC1122.

Обычно вы должны добавить параметр TCP_QUICKACK к вашему сокету Linux TCP в отключить отложенный ACK, но я думаю, что это не очевидно с JavaScript Node.js API (я видел только вариант socket.setNoDelay для TCP_NODELAY) .

Итак, ваша идея применить общесистемное изменение стека TCP кажется хорошей, но я не нашел sysctl соответствующее этому поведению опции сокета. Вот еще один полный список с пояснениями.

person Yves Martin    schedule 02.08.2012
comment
Это похоже на правильный ответ, если нет более подробной информации, которую ОП не предоставил. - person This; 02.08.2012
comment
Спасибо за Ваш ответ! У меня есть несколько дополнительных вопросов. Это действительно для FIN ACK или только для одного ACK. Можете ли вы сказать, почему ядро ​​​​задержало этот FIN / ACK. В данных tcpflow есть ровно один ACK на пакет, исходящий от сервера. Почему ядро ​​задержало клиент FIN/ACK. Это могло бы избежать отправки ACK каждого пакета «данных». Но выбрать задержку FIN/ACK? Это возможно? - person Tereska; 02.08.2012
comment
Пожалуйста, прочитайте раздел 4.2.3.2 RFC1122... он не относится к пакетам FIN. Я согласен с вами, что нет причин задерживать пакет FIN+ACK без данных. Я приглашаю вас связаться с командой TCP ядра Linux по LKML или открытому исходному коду для реализации логики отложенного ACK. Вероятно, можно выполнить оптимизацию и, по крайней мере, новый переключатель sysctl, чтобы избежать такого поведения. - person Yves Martin; 02.08.2012
comment
LKML (netdev) говорит, что это проблема приложения. marc.info/?l=linux-netdev&m=134409837229053&w=2 - person Tereska; 04.08.2012
comment
Вы говорите, что задержка влияет только на 1% трафика. Таким образом, это происходит не из-за самой обработки кода приложения, а может исходить из самого механизма JavaScript, например, из-за задержки сборки мусора, чтобы отбросить сокет после использования... Вы должны попытаться запустить свой код с помощью альтернативных механизмов JavaScript и разных браузеров. Вы нашли странные строки в dmesg? трассировка браузера возможна, но ее будет очень сложно проанализировать. Возможно, трассировка кода, работающего в автономном движке JavaScript, является вариантом для получения диагностики. - person Yves Martin; 07.08.2012