#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 .