Задержка в сокете Java на 30 секунд?

#java #sockets #tcp #latency

#java #сокеты #tcp #задержка

Вопрос:

На моем TCP-сервере, который написан на Java, иногда у случайного клиента задержка составляет от 5 до 60 секунд. Когда это происходит, на сервере остается много свободной памяти и процессора. Сокет уже открыт, когда это происходит.

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

Я отключил Nagle, но я не понимаю, как Nagle может вызвать такую задержку.

Я не очень конкретен, потому что меня это смущает. Что теоретически может вызвать это?

Другое дело: когда у одного из клиентов такая сильная задержка, другие клиенты работают нормально. И все они находятся на одном интерфейсе Ethernet сервера. Я не могу объяснить такую вещь.

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

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

2. да, у меня есть. взаимоблокировок нет

Ответ №1:

Что теоретически может вызвать это?

Теоретические причины включают:

  • Ошибка в клиентском коде. Трудно сказать, что это было бы, не глядя на код, но я бы заподозрил проблему с потоками, уведомлениями или синхронизацией.

  • Ошибка в коде сервера. Трудно сказать, что это будет … как указано выше.

  • Ошибка JVM. Маловероятно.

  • Ошибка операционной системы. Маловероятно.

  • Проблема с сетью. Возможно, между клиентом и сервером неисправен или неправильно настроен коммутатор / шлюз / брандмауэр. Возможно, есть проблема с сетью и виртуализацией.

Я думаю, вам нужно использовать что-то вроде WireShark, чтобы узнать, можете ли вы видеть, когда пакеты передаются по проводам, и так далее. Это должно помочь немного сузить его.


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

Есть еще несколько вопросов, которые нужно задать себе:

  • Это происходит только с «определенными» клиентами. Так чем же они отличаются?

  • Процесс Java продолжается «как если бы» данные были отправлены. Итак, почему он думает, что данные были отправлены?

  • Сервер не отправляет / не получает данные «физически». Что вы подразумеваете под «физически»? Почему вы знаете / считаете, что это так? Заблокирован ли поток сервера при чтении? Или он заблокирован при прослушивании? Действительно ли данные вообще поступили на серверный компьютер?

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

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

2. @Joel — проблемы, которые трудно воспроизвести, часто оказываются ошибками потоковой передачи / синхронизации. К сожалению, лучший способ найти такие ошибки — для тех, кто действительно понимает потоковую обработку и модель памяти Java, тщательно проанализировать исходный код.

3. По-видимому, это не связано с синхронизацией. Это происходит в инструкциях outputstream.write() и inputstream.read(). Разве не возможно, что интернет-маршрутизация в некоторых случаях займет много секунд при уже открытом сокете? Или это невозможно?

Ответ №2:

Одной из причин может быть забывание сбросить OutputStream клиенту. Java или базовая ОС могут ждать, пока дополнительные данные заполнят пакет.

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

1. Это очень полезный совет. 1

2. спасибо, это наверняка возможно. но в моей программе это не так. Я отправляю сообщения только одним методом, который не имеет возврата, и его последняя инструкция — flush .