среда, 9 ноября 2016 г.

Анализ с помощью tcpdump причин потерь пакетов между клиентом и сервером.

Пришлось решать интересную проблему с сетью, хочется зафиксировать в тексте для истории. Это может быть интересно администраторам и программистам сетей.

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

Описание среды

 

Сервер у нас - микропроцессорная сборка Vortex с запущенной на нем ОС QNX 6.5.0. Сетевая плата на нём поддерживает скорости до 100 Мб/с Full duplex. Серверное приложение постоянно висит в памяти и слушает фиксированный порт (в нашем случае 502, это будет видно ниже в логах). При получении запроса сервер его обрабатывает, шлёт ответ клиенту, и переходит к ожиданию очередного запроса.
Клиентское приложение написано под Windows. Сетевая карта на клиентской машине, где воспроизводилась ошибка поддерживает 1 Гбит/с. В процессе работы клиент по своей инициативе постоянно шлёт по Ethernet запросы серверу (5 запросов в секунду, размер одного запроса от 2-ух до ~100 байт). Сервер рождает за 10-250 мс ответ и шлёт его назад (размер ответа меньше 100 байт). Пока клиент не получит ответ на предыдущий запрос, новый запрос не посылается. Если в течение 2 секунд клиент не получает ответ на свой запрос, пользователю выкидывается окно с сообщением об ошибке, и связь (сокет) закрывается.
Во время отладки сервер и клиент соединены между собой одним Ethernet кабелем без промежуточных железяк: свитчей и пр.

Исследование


Анализ имеющихся логов программы-клиента выявил, что клиентское ПО не получает ответ на свой очередной запрос в течение таймаута и честно отключается, предупреждая об этом пользователя
Копание логов работы программы-сервера показало, что сервер получает запрос, успешно формирует ответ и шлёт ответ клиенту, причем функция отсылки ответа не давала ошибок. Функция отправки ответа в сервере из стандартной библиотеки:
int snd = send(clientSocket, (char*)answer, AnswerFromTiva_Len + 6, 0); // 6 - заголовок пакета в TCP-Modbus

Клиентский код получения ответа на запрос:
int retval = rsocket.CAsyncSocket::Receive(buffer, buf_size); //неблокирующее чтение

Код отправки и получения данных был отлажен годами, и работал на многих объектах, жалоб на эти места не было. Очень не хотелось трогать этот код, и, забегая вперёд скажу, что его и не нужно было трогать )

Возникает странная ситуация - сервер отправляет ответ на запрос клиенту, но клиент его не получает за время таймаута! Процессоры машин незагружены. Аппаратно клиентская и серверная машины связаны одним кабелем Ethernet, без свитчей и пр. Т.е. одна сторона кабеля вставлена в сетевую карту сервера, а другая в сетевой разъем клиента, и тяжело предположить в данном случае, куда может подеваться пакет. Auto negotiation (автоопределение), вызывающий регулярный стопор сети для анализа, нужно отключить:



Запускаем на сервере и клиенте tcpdump без фильтров:

tcpdump -i 3 -s 130 -w tcplog.file

Полученные двоичные файлы с сервера и клиента открываем в бесплатной программе WireShark.

При отсутствии ошибок связи tcpdump демонстрировал одни и те же пакеты на сервере и на клиенте.


Лог сервера в месте возникновения ошибки (ip 192.168.1.22):


Лог клиента (ip 192.168.1.143):


В логе видны провалы непонятной природы в передаче данных.
Смотрим системный журнал на Windows. Ух ты! Вот оно что:


Intel(R) 82579V Gigabit это как раз моя сетевая карточка.
Рядом ещё запись от источника BROWSER:
Драйвер браузера сети инициировал выборы в сети \Device\NetBT_Tcpip_{8C04992F-E979-4A40-ACD2-539101DE4201}, так как был остановлен основной браузер сети.
и запись спустя 3 секунды:
Network link has been established at 100Mbps full duplex.

Несмотря на этот "link is disconnected", никакие сессии между клиентом и сервером не обрываются, поэтому обычно эта проблема остается незамеченной.
Промежуточный вывод: машина клиента обрывает линк между клиентом и сервером на несколько секунд.

Смотрим режимы работы сети на клиенте и сервере. На клиенте, как написано выше, гигабитная карточка работает на 100 Мб/с и полном дуплексе, на сервере:

# nicinfo
en0:
  DMP vortex-R6040 Ethernet Controller

  Physical Node ID ..................... 001BEB 64D211
  Current Physical Node ID ............. 001BEB 64D211
  Current Operation Rate ............... 100.00 Mb/s half-duplex


На сервере установлен полудуплексный режим. Это сложилось исторически. Принудительно устанавливаем полный дуплекс, чтобы режимы клиента и сервера соответствовали друг другу. Оставляем сервер и клиент крутиться на ночь, и... что ж это такое, опять обрывы связи! Смотрим на кабель, соединяющий клиента и сервера, выясняется, что это 1 Гбит/с кроссовый. Отыскиваем кабель 100 Мб/с кроссовер, оставляем систему крутиться на ночь - нет ошибок, оставляем на выходные - нет ошибок в понедельник. Ура! Несмотря на принудительно выставленный режим на клиенте 100 Мб/с, "умная" сетевая карточка определяла, что распиновка кабеля рассчитана на скорость 1Гбит/с, и пыталась дёргать режимы. Только при полном соответствии режима работы карты и распиновки кабеля сетевой линк перестал отключаться.

Вывод

 

Выводы для опытных сетевиков окажутся банальными. Мне незнание стоило пары недель длительных тестов. При проблемах в сети не забываем посмотреть системный журнал операционной системы, там могут оказаться полезные для нас записи от сетевых служб. Внимательно смотрим скорость и режим работы сети (дуплексность), распиновку сетевого кабеля. Для тестовых задач необходимо отключить автоопределение сети и принудительно установить одинаковые режимы работы сетевых карт на клиенте и сервере. Кабель должен соответствовать режиму работы сети. Возможно, промежуточные свитчи между сервером и клиентом могут помочь решить проблемы с сетью, согласовав режимы работы сети клиента и сервера.

Конец.

Комментариев нет:

Отправить комментарий