Сокеты дейтаграмм UDP. Каковы возможные причины сбоя send() для «Нет доступного места в буфере»

Я тестирую свой код на дешевом дроплете Digital Ocean (2 ГБ оперативной памяти, но я также пытался добавить 4 ГБ подкачки, и это ничего не изменило).

Часть моей программы имеет много клиентских сокетов DGRAM UDP, открытых для различных локальных портов (от/до 127.0.0.1).

Иногда без отправки безумного количества данных вызов send() завершается с ошибкой No buffer space available (ошибка 105).

Затем моя программа пытается использовать все остальные доступные сокеты (для других локальных портов), но все они терпят неудачу одновременно.

Я установил /proc/sys/net/core/wmem_max/proc/sys/net/core/rmem_max) на 16 МБ, а для каждого из этих сокетов setsockopt SOL_SOCKET, SO_SNDBUF установлено значение 8 МБ. Ни один из них ничего не меняет.

Как send() может потерпеть неудачу с No buffer space available? Разве это не должно происходить только тогда, когда мы посылаем () слишком быстро? Но здесь это локально, и я не отправляю много данных.

Что меня больше всего озадачивает, так это то, что когда процесс повторяет попытку любого другого сокета, он получает ту же ошибку. Разве буферы сокетов не должны быть полностью независимыми?

Каковы возможные причины?

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
1 096
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ошибка No buffer space available не означает, что буфер сокета заполнен. Это означает, что ядро ​​Linux не может выделить память для буфера сокета. Для любого буфера сокета нет памяти, поэтому, когда возникает это условие, невозможно отправить какие-либо данные через любой сокет, пока не будет освобождена часть памяти. Увеличение wmem_max и rmem_max может еще больше усугубить проблему, поскольку они могут увеличить потребление памяти на сокет. Вы можете проверить общее потребление памяти и сколько памяти выделено для буферов сокета udp:

$ cat /proc/net/sockstat
sockets: used 315
TCP: inuse 8 orphan 0 tw 0 alloc 13 mem 1
UDP: inuse 3853 mem 240812
UDPLITE: inuse 0
RAW: inuse 0
FRAG: inuse 0 memory 0

Сокеты UDP в этом примере используют 240812 страниц на 4 КБ, что составляет ~ 940 МБ. Открыто 3853 сокета

$ free -h
              total        used        free      shared  buff/cache   available
Mem:           1.9G        1.8G         75M        1.2M         66M         28M
Swap:            0B          0B          0B

Система в этом примере имеет 2 ГБ физической памяти и очень мало свободной памяти. Высока вероятность того, что функция send завершается с ошибкой No buffer space available.

Если память фактически потребляется буферами сокетов, добавление подкачки вряд ли поможет, потому что, насколько мне известно, буферы не могут быть заменены.

Вы можете попробовать виртуальную машину с большим объемом памяти. Это может помочь или, по крайней мере, отсрочить проблему.

Вы также можете провести аудит приложения и проверить, как используются сокеты. Высокое потребление памяти буферами сокетов UDP может быть вызвано ошибкой в ​​приложении или неправильным дизайном. Например, если приложение прослушивает сокет UDP и есть данные, но приложение ничего не читает, тогда ядро ​​​​не освобождает память до тех пор, пока процесс не завершится или пока приложение не вызовет recv. Много открытых сокетов без вызова recv может использовать память.

Другими словами, отдельные буферы сокетов не заполнены (SO_SNDBUF), но все они вместе занимают так много, что ядро ​​не может найти для них больше (без подкачки) памяти? Что касается увеличения wmem_max/rmem_max и SO_SNDBUF, кто-то здесь упомянул, что память на самом деле не используется, пока не понадобится: stackoverflow.com/questions/64523733/… Вы согласны?

FlorianB 13.12.2020 22:17

Мне удалось воспроизвести при проверке как /proc/net/sockstat, так и free -h, и 180 сокетов в среднем никогда не занимают более 80 страниц (потому что большинство из них просто ждут, чтобы их использовали), но память без подкачки, тем не менее, достигает критически низкой точки, при которой проблема бывает. Спасибо! Теперь я знаю, что с самими сокетами все в порядке, просто они выходят из строя первыми, когда системе не хватает памяти.

FlorianB 14.12.2020 00:00

Да, память для буфера выделяется по мере необходимости — обычно при получении данных или вызове приложения send. Если буфер сокета заполнен (данные ожидают отправки или данные ожидают чтения), тогда ядро ​​отбрасывает некоторые данные, но не сообщает об ошибке. Это разрешено для UDP. Но как вы написали - проблема в общем потреблении памяти. 80 страниц для буферов сокетов - это не очень много. Там наверное другой пожиратель памяти.

Zaboj Campula 14.12.2020 08:46

Другие вопросы по теме