Миграция Solaris в RH: задержка в сети, размер окна tcp и другие параметры tcp - PullRequest
3 голосов
/ 08 июня 2010

У меня есть клиент-серверное приложение (Java), которое я перевожу с Solaris на RH Linux. с тех пор, как я начал работать с ним в RH, я заметил некоторые проблемы, связанные с задержкой. Мне удалось выделить проблему, которая выглядит так:

  • клиент отправляет 5 сообщений (по 32 байта каждое) подряд (одна и та же временная метка приложения) на сервер.
  • эхо-сообщения сервера.
  • клиент получает ответы и печатает время приема-передачи для каждого сообщения.

в Solaris все хорошо: я получаю ВСЕ 5 ответов одновременно, примерно через 80 мс после отправки оригинальных сообщений (клиент и сервер находятся на расстоянии нескольких тысяч миль друг от друга: мой RTT пинга равен 80 мс, все нормально).

в RH первые 3 сообщения отражаются нормально (они приходят через 80 мс после отправки), однако следующие 2 сообщения приходят через 80 мс (итого 160 мс RTT).

картина всегда одна и та же. явно выглядело как проблема TCP.

на моем солярисе я ранее настроил стек tcp с двумя конкретными опциями:

  1. отключить алгоритм Nagle в глобальном масштабе
  2. установить tcp_deferred_acks_max в 0

на RH невозможно отключить Nagle глобально, но я отключил его на всех сокетах моих приложений (TCP_NODELAY).

поэтому я начал играть с tcpdump (на сервере) и сравнил оба вывода:

SOLARIS

 22 2.085645    client         server          TCP      56150 > 6006 [PSH, ACK] Seq=111 Ack=106 Win=66672 Len=22    "MSG_1 RCV"
 23 2.085680    server         client          TCP      6006 > 56150 [ACK] Seq=106 Ack=133 Win=50400 Len=0
 24 2.085908    client         server          TCP      56150 > 6006 [PSH, ACK] Seq=133 Ack=106 Win=66672 Len=22    "MSG_2 RCV"
 25 2.085925    server         client          TCP      6006 > 56150 [ACK] Seq=106 Ack=155 Win=50400 Len=0
 26 2.086175    client         server          TCP      56150 > 6006 [PSH, ACK] Seq=155 Ack=106 Win=66672 Len=22    "MSG_3 RCV"
 27 2.086192    server         client          TCP      6006 > 56150 [ACK] Seq=106 Ack=177 Win=50400 Len=0
 28 2.086243    server         client          TCP      6006 > 56150 [PSH, ACK] Seq=106 Ack=177 Win=50400 Len=21    "MSG_1 ECHO"
 29 2.086440    client         server          TCP      56150 > 6006 [PSH, ACK] Seq=177 Ack=106 Win=66672 Len=22    "MSG_4 RCV"
 30 2.086454    server         client          TCP      6006 > 56150 [ACK] Seq=127 Ack=199 Win=50400 Len=0
 31 2.086659    server         client          TCP      6006 > 56150 [PSH, ACK] Seq=127 Ack=199 Win=50400 Len=21    "MSG_2 ECHO"
 32 2.086708    client         server          TCP      56150 > 6006 [PSH, ACK] Seq=199 Ack=106 Win=66672 Len=22    "MSG_5 RCV"
 33 2.086721    server         client          TCP      6006 > 56150 [ACK] Seq=148 Ack=221 Win=50400 Len=0
 34 2.086947    server         client          TCP      6006 > 56150 [PSH, ACK] Seq=148 Ack=221 Win=50400 Len=21    "MSG_3 ECHO"
 35 2.087196    server         client          TCP      6006 > 56150 [PSH, ACK] Seq=169 Ack=221 Win=50400 Len=21    "MSG_4 ECHO"
 36 2.087500    server         client          TCP      6006 > 56150 [PSH, ACK] Seq=190 Ack=221 Win=50400 Len=21    "MSG_5 ECHO"
 37 2.165390    client         server          TCP      56150 > 6006 [ACK] Seq=221 Ack=148 Win=66632 Len=0
 38 2.166314    client         server          TCP      56150 > 6006 [ACK] Seq=221 Ack=190 Win=66588 Len=0
 39 2.364135    client         server          TCP      56150 > 6006 [ACK] Seq=221 Ack=211 Win=66568 Len=0

REDHAT

 17 2.081163    client         server          TCP      55879 > 6006 [PSH, ACK] Seq=111 Ack=106 Win=66672 Len=22    "MSG_1 RCV"
 18 2.081178    server         client          TCP      6006 > 55879 [ACK] Seq=106 Ack=133 Win=5888 Len=0
 19 2.081297    server         client          TCP      6006 > 55879 [PSH, ACK] Seq=106 Ack=133 Win=5888 Len=21 "MSG_1 ECHO"
 20 2.081711    client         server          TCP      55879 > 6006 [PSH, ACK] Seq=133 Ack=106 Win=66672 Len=22    "MSG_2 RCV"
 21 2.081761    client         server          TCP      55879 > 6006 [PSH, ACK] Seq=155 Ack=106 Win=66672 Len=22    "MSG_3 RCV"
 22 2.081846    server         client          TCP      6006 > 55879 [PSH, ACK] Seq=127 Ack=177 Win=5888 Len=21 "MSG_2 ECHO"
 23 2.081995    server         client          TCP      6006 > 55879 [PSH, ACK] Seq=148 Ack=177 Win=5888 Len=21 "MSG_3 ECHO"
 24 2.082011    client         server          TCP      55879 > 6006 [PSH, ACK] Seq=177 Ack=106 Win=66672 Len=22    "MSG_4 RCV"
 25 2.082362    client         server          TCP      55879 > 6006 [PSH, ACK] Seq=199 Ack=106 Win=66672 Len=22    "MSG_5 RCV"
 26 2.082377    server         client          TCP      6006 > 55879 [ACK] Seq=169 Ack=221 Win=5888 Len=0
 27 2.171003    client         server          TCP      55879 > 6006 [ACK] Seq=221 Ack=148 Win=66632 Len=0
 28 2.171019    server         client          TCP      6006 > 55879 [PSH, ACK] Seq=169 Ack=221 Win=5888 Len=42 "MSG_4 ECHO + MSG_5 ECHO"
 29 2.257498    client         server          TCP      55879 > 6006 [ACK] Seq=221 Ack=211 Win=66568 Len=0

Итак, я получил подтверждение, что для RH все не работает должным образом: пакет 28 отправляется СЛИШКОМ ПОЗЖЕ, похоже, что сервер ожидает ACK пакета 27, прежде чем что-либо делать.

мне кажется это наиболее вероятная причина ...

тогда я понял, что параметры "Win" отличаются для дампов Solaris и RH: 50400 для Solaris, только 5888 для RH. это еще один намек ...

Я прочитал документ о окне слайдов и окне буфера и поиграл с rcvBuffer & sendBuffer в java на моих сокетах, но мне так и не удалось изменить это значение 5888 на что-либо другое (я проверял каждый раз непосредственно с помощью tcpdump).

кто-нибудь знает, как это сделать? Мне трудно получить точную информацию, так как в некоторых случаях есть «автоматическое согласование», которое мне, возможно, придется обойти, и т. Д ...

В конце концов мне удалось лишь частично избавиться от моей первоначальной проблемы, установив для параметра «tcp_slow_start_after_idle» значение 0 на RH, но это не изменило параметр «win» вообще. та же проблема возникла для первых 4 групп по 5 сообщений с повторной передачей TCP и ACK TCP Dup в tcpdump, затем проблема полностью исчезла для всех следующих групп из 5 сообщений.

Мне не кажется, что это очень чистое и / или общее решение. Мне бы очень хотелось воспроизвести одинаковые условия в обеих ОС.

Я буду продолжать исследования, но любая помощь от гуру TCP будет принята с благодарностью!

1 Ответ

1 голос
/ 08 июня 2010

Похоже, что в Red Hat включается алгоритм предотвращения перегрузки.

Обратите внимание, что с пакета 26 сервер видел и ACKed все от клиента, но клиент только ACKed исходный SYN сервера - он еще не ACKed любых сообщений сервера. Обратите также внимание, что пакет 27, который снова запускает процесс, является клиентом, который подтверждает первые две партии данных сервера (пакеты 19 и 22).

Какой алгоритм управления перегрузкой использует коробка Red Hat? (/proc/sys/net/ipv4/tcp_congestion_control) - вы можете попробовать переключиться на один из других доступных.

...