Назад |
Перейти на главную страницу
Потеря TCP-пакетов на SQL-сервере
Там, где я работаю, у нас были проблемы с подключением к базе данных. Мы получаем много сбоев, которые на стороне клиента отображаются как «сбой recv». Я использовал Wireshark, чтобы попытаться отладить проблему, и пошел немного дальше, но теперь я в значительной степени застрял.
Сначала немного об инфраструктуре:
- Внутренние IT-системы работают как виртуальные машины (серверы) на 1-2 физических машинах. Они состоят из нескольких приложений на Glassfish, а также SQL-сервера.
- Кроме того, есть несколько серверов у внешнего провайдера, в том числе и SQL-сервер.
- Между внутренней и внешней системами есть межсетевой экран, который маршрутизирует трафик.
Проблема заключается в связи между приложениями во внутренней зоне и базой данных во внешней зоне. Проблема возникает только на некоторых (в то время фактически только на одном) виртуальных серверах и не зависит от приложения (это происходит как через пулы соединений Glassfish и JDBC, так и через SQL-клиенты, такие как SQuirreL).)
И это становится еще более странным, поскольку небольшие SQL-операторы выполняются, но когда они достигают определенной длины, ничего не происходит, пока соединение не будет закрыто на стороне клиента (с ошибкой recv).
Вот что я обнаружил с помощью Wireshark:
- На работающих серверах небольшой запрос SQL отображается в Wireshark как один пакет TDS с прямым ответом на пакет TDS (не отображаются подтверждения TCP и т. Д.). Большие запросы обычно сначала отправляются как TDS, а затем повторно отправляются по частям. часть как TCP, подтверждена правильно, а затем возвращается результат. (В одном случае я увидел, что сначала он попробовал 2400-байтовый TDS, затем 1514-байтовый TCP, а затем 590-байтовый TCP и получил подтверждения для последних ..)
- На сервере, который не работает, небольшие запросы отправляются в виде TDS-пакета (и это работает). С другой стороны, при больших запросах он сначала пытается отправить весь запрос как TCP-пакет, а затем получает ACK с seq и ack = 1 (означает, что данные не получены?), затем он пытается отправить 1514-байтовый TCP-пакет, не получая обратно ACK. Он пытается сделать это еще несколько раз, прежде чем соединение будет разорвано.
- Если максимальный результат - это билет в SQuirreL, он сначала отправляет небольшой TDS-пакет с указанием ограничений на результат, затем пытается отправить запрос, но получает только повторную отправку подтверждения первого из них. При повторной отправке запроса подтверждения не принимаются.
Я в значительной степени ослеплен тем, где искать дальше, есть ли у кого-нибудь указатели?
Обновление: перезапуск виртуального сервера решил проблему - по крайней мере, пока ..
Обновление №2: .. и теперь проблема вернулась ..
У нас был сетевой эксперт, который посмотрел на это, и выяснилось, что это вызвано ошибочными настройками MTU. Насколько я понимаю, большая часть сетевой инфраструктуры поддерживает jumbo-кадры, поэтому MTU был установлен на 9000. Но был один компонент (VPN-туннель), который не поддерживал это, поэтому кадры более определенного размера были усечены. Изменение всех настроек MTU 1500/1460 устранило проблему.