Проблема производительности Socket Java TCP/IP

Наше приложение быстро считывает данные по сокетам TCP/IP в Java. Мы используем библиотеку NIO с неблокирующими сокетами и селектором, чтобы указать готовность к чтению. В среднем общее время обработки для считывания и обработки прочитанных данных составляет субмиллисекунду. Однако мы часто наблюдаем всплески в 10-20 миллисекунд. (работает в Linux).

Используя tcpdump, мы можем видеть разницу во времени между чтением tcpdump двух конфиденциальных сообщений и сравнить это с временем приложений. Мы видим, что tcpdump не задерживается, тогда как приложение может показывать 20 миллисекунд.

Мы уверены, что это не GC, потому что в журнале GC практически нет полного GC, а в JDK 6 (по тому, что я понимаю) GC по умолчанию параллелен, поэтому он не должен приостанавливать потоки приложения (если только не делать Полный GC).

Он выглядит почти так, как будто существует некоторая задержка для метода Java Selector.select(0), чтобы вернуть готовность к чтению, потому что на уровне TCP данные уже доступны для чтения (и tcpdump читает его).

Дополнительная информация: при пиковой нагрузке мы обрабатываем около 6000 x 150 байт за сообщение или около 900 МБ в секунду.

Ответ 1

коллекция eden по-прежнему подвержена паузе STW, поэтому 20 мс могут быть совершенно нормальными в зависимости от поведения размещения и размера/размера кучи живого набора.

Ответ 2

Является ли ваш Java-код запущенным под RTLinux или другим дистрибутивом с жесткой возможностью планирования в реальном времени? Если нет, 10-20 мс джиттера во время обработки кажется вполне разумным и ожидаемым.

Ответ 3

У меня была такая же проблема в java-сервисе, над которым я работаю. При отправке одного запроса повторно от клиента сервер будет блокировать в том же месте в потоке в течение 25-35 мс. Отключение алгоритма Nagle в сокете исправил это для меня. Это можно сделать, вызвав setTcpNoDelay (true) на Socket. Это может привести к увеличению перегрузки сети, поскольку ACK теперь будут отправляться как отдельные пакеты. См. http://en.wikipedia.org/wiki/Nagle%27s_algorithm для получения дополнительной информации о алгоритме Нагле.

Ответ 4

Из tcpdump faq:

КОГДА ВРЕМЯ ВЫКЛЮЧАЕТСЯ ПАКЕТ? КАК ТОЧНО - ВРЕМЕННЫЕ СТАМПЫ?

В большинстве ОС, на которых tcpdump и запуск libpcap, время пакета с печатью как часть процесса драйвер сетевого интерфейса или сетевой стек, обрабатывающий его. Это означает, что пакет не является временем с печатью в тот момент, когда он прибывает на сетевом интерфейсе; после пакет поступает в сеть интерфейса, будет задержка до прерывание доставляется или сетевого интерфейса (т.е. сетевой интерфейс может не прерываться хозяин немедленно - водитель может быть настроен для опроса интерфейса, если сетевой трафик тяжелый, чтобы уменьшить количество прерываний и процесс больше пакетов за прерывание), и там будет являться дополнительной задержкой между точка, с которой начинается прерывание обрабатывается, а отметка времени - генерируется.

Итак, вероятность того, что отметка времени сделана на уровне привилегированного ядра, а потерянные 20 мс - накладные расходы на контекст обратно в пространство пользователя и на Java и логику селектора сетей JVM. Без анализа системы в целом я не думаю, что можно сделать утвердительный выбор причины.