[c++] Причины падения пакетов UDP Linux



1 Answers

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

Аналогично, хотя часто менее продуктивным является привязка потока для приема к одному ядру, так что вы не страдаете накладными расходами на переключение между ядрами и связанными с ним кешами.

Question

У меня есть приложение на Linux C ++, которое получает последовательные UDP-пакеты. Из-за последовательности, я могу легко определить, когда пакет потерян или переупорядочен, то есть когда встречается «пробел». Система имеет механизм восстановления для устранения пробелов, однако лучше всего избегать пробелов в первую очередь. Используя простой пакетный сниффер на основе libpcap, я определил, что в данных на аппаратном уровне нет пробелов. Тем не менее, я вижу много пробелов в своем приложении. Это говорит о том, что ядро ​​отбрасывает пакеты; это подтверждается просмотром файла / proc / net / snmp . Когда мое приложение сталкивается с пробелом, счетчик Udp InErrors увеличивается.

На уровне системы мы увеличили максимальный буфер приема:

# sysctl net.core.rmem_max
net.core.rmem_max = 33554432

На уровне приложения мы увеличили размер буфера приема:

int sockbufsize = 33554432
int ret = setsockopt(my_socket_fd, SOL_SOCKET, SO_RCVBUF,
        (char *)&sockbufsize,  (int)sizeof(sockbufsize));
// check return code
sockbufsize = 0;
ret = getsockopt(my_socket_fd, SOL_SOCKET, SO_RCVBUF, 
        (char*)&sockbufsize, &size);
// print sockbufsize

После вызова метода getsockopt () печатное значение всегда равно 2x, на которое оно установлено (67108864 в приведенном выше примере), но я считаю, что этого следует ожидать.

Я знаю, что неспособность быстро использовать данные может привести к потере пакетов. Тем не менее, все это приложение выполняет проверку последовательности, а затем выталкивает данные в очередь; фактическая обработка выполняется в другом потоке. Кроме того, машина современная (Dual Xeon X5560, 8 ГБ оперативной памяти) и очень легко загружена. У нас буквально десятки одинаковых приложений, получающих данные с гораздо более высокой скоростью, которые не испытывают этой проблемы.

Помимо слишком медленного использования приложений, есть ли другие причины, по которым ядро ​​Linux может отказаться от пакетов UDP?

FWIW, это на CentOS 4, с ядром 2.6.9-89.0.25.ELlargesmp.




Мне не хватает репутации, чтобы комментировать, но, как и у @racic, у меня была программа, в которой у меня был один поток получения, и один поток обработки с блокирующей очередью между ними. Я заметил ту же проблему с удалением пакетов, потому что принимающий поток ожидал блокировки в очереди блокировки.

Чтобы решить эту проблему, я добавил меньший локальный буфер в принимающий поток, и если бы он только вставлял данные в буфер, тогда он не был заблокирован (с использованием std :: mutex :: try_lock).




Related