Java IOException: Никакое пространство буфера, доступное при отправке пакетов UDP на Linux

Не знаю, почему все эти ответы танцуют вокруг того, что я считаю правильным решением, но для этого стоит использовать то, что я использую:

Создайте псевдоним:

git config --global alias.coa '!git add -A && git commit -m'

Добавить все файлы & amp; совершить с сообщением:

git coa "A bunch of horrible changes"

ПРИМЕЧАНИЕ: coa - сокращение от commit all и может быть заменено всем, что душе угодно

5
задан auramo 25 June 2009 в 18:52
поделиться

4 ответа

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

echo 1048576 > /proc/sys/net/core/wmem_max
echo 1048576 > /proc/sys/net/core/wmem_default
echo 1048576 > /proc/sys/net/core/rmem_max
echo 1048576 > /proc/sys/net/core/rmem_default

От имени пользователя root.

Или используйте sysctl

sysctl -w net.core.rmem_max=8388608 

Существует множество сетевых опций

См. Linux Network Tuning by IBM и Дополнительная информация о настройке

3
ответ дан 18 December 2019 в 13:18
поделиться

Может быть немного сложно, но, насколько я знаю, Java использует шаблон SPI 1 для сетевой подбиблиотеки. Это позволяет вам изменить реализацию, используемую для различных сетевых операций. Если вы используете OpenJDK, вы можете получить некоторые подсказки, как и что заключить в свою реализацию. Затем в вашей реализации вы замедляете ввод-вывод, например, с помощью некоторого сна.

Или, просто для удовольствия, вы можете переопределить DatagramSocket по умолчанию с помощью вашей модифицированной реализации. У него должно быть то же имя пакета, и, насколько я знаю, он будет иметь приоритет над классом JRE по умолчанию. По крайней мере, этот метод работал у меня с какой-то ошибочной сторонней библиотекой.

Изменить:

1 Интерфейс поставщика услуг - это метод разделения клиентского и служебного кода в API. Это разделение позволяет реализовать разные клиентские и разные провайдеры. Обычно его можно узнать по имени, оканчивающемуся на Impl , как и в трассировке стека java.net. PlainDatagramSocketImpl - это реализация провайдера, где DatagramSocket - это клиентский API.

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

Другой вариант - определить неправильно работающий класс в библиотеке, выполнить JAD и исправить. Затем замените исходный файл класса в библиотеке.

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

Другой вариант - определить неправильно работающий класс в библиотеке, выполнить JAD и исправить. Затем замените исходный файл класса в библиотеке.

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

Другой вариант - определить неправильно работающий класс в библиотеке, выполнить JAD и исправить. Затем замените исходный файл класса в библиотеке.

1
ответ дан 18 December 2019 в 13:18
поделиться

Я также сейчас вижу эту проблему как в Debian, так и в RHEL. На данный момент я считаю, что изолировал его от сетевой карты и / или драйвера сетевой карты. Какая у вас конфигурация оборудования также демонстрирует эту проблему? Похоже, что это происходит только на новых серверах Dell PowerEdge, которые мы недавно приобрели, которые имеют сетевые карты Broadcom Corporation NetXtreme II BCM5708 Gigabit Ethernet.

Я тоже могу подтвердить, что это быстрое создание исходящих UDP-пакетов на множество различных IP-адресов. окно. Я попытался написать простое приложение Java, которое могло бы его воспроизвести (так как у нас это происходит с snmp4j).

ИЗМЕНИТЬ

Посмотрите мой ответ здесь: Java IOException: при отправке UDP-пакетов нет свободного места в буфере в Linux

0
ответ дан 18 December 2019 в 13:18
поделиться

Я наконец определил, в чем проблема. Исключение Java IOException вводит в заблуждение, поскольку это «Нет доступного буферного пространства», но основная проблема заключается в том, что локальная таблица ARP заполнена. В Linux поиск по таблице ARP по умолчанию - 1024 (файлы / proc / sys / net / ipv4 / neigh / default / gc_thresh1, / proc / sys / net / ipv4 / neigh / default / gc_thresh2, / proc / sys / net / ipv4 /neigh/default/gc_thresh3).

Что происходило в моем случае (и я предполагаю, что ваш случай), так это то, что ваш код Java отправляет пакеты UDP с IP-адреса, который находится в той же подсети, что и ваши адреса назначения. В этом случае компьютер Linux выполнит поиск ARP, чтобы преобразовать IP-адрес в аппаратный MAC-адрес. Поскольку вы отправляете пакеты на множество разных IP-адресов, локальная таблица ARP заполняется быстро, достигает 1024, и именно тогда возникает исключение Java.

Решение простое: либо увеличьте лимит, отредактировав файлы, о которых я упоминал ранее. или переместите свой сервер в подсеть, отличную от адресов назначения, в результате чего Linux-сервер больше не будет выполнять поиск ARP соседей (вместо этого будет обрабатываться маршрутизатором в сети).

10
ответ дан 18 December 2019 в 13:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: