c++ - comando - desventajas de debian
Las causas de los paquetes de Linux UDP caen (4)
Si tiene más subprocesos que núcleos e igual prioridad de subprocesos entre ellos, es probable que el subproceso receptor pierda tiempo para eliminar el búfer entrante. Considere ejecutar ese hilo en un nivel de prioridad más alto que los demás.
Del mismo modo, aunque a menudo menos productivo es vincular el hilo para recibir a un núcleo para que no sufra gastos generales de cambio entre los núcleos y las descargas de caché asociadas.
Tengo una aplicación Linux C ++ que recibe paquetes UDP secuenciados. Debido a la secuencia, puedo determinar fácilmente cuándo se pierde o se reordena un paquete, es decir, cuándo se encuentra un "espacio". El sistema tiene un mecanismo de recuperación para manejar las brechas, sin embargo, lo mejor es evitar las brechas en primer lugar. Utilizando un simple sniffer de paquetes basado en libpcap, he determinado que no hay lagunas en los datos a nivel de hardware. Sin embargo, veo muchas lagunas en mi aplicación. Esto sugiere que el kernel está dejando caer paquetes; se confirma al mirar el archivo / proc / net / snmp . Cuando mi aplicación encuentra un espacio, aumenta el contador Udp InErrors .
En el nivel del sistema, hemos aumentado el buffer de recepción máximo:
# sysctl net.core.rmem_max
net.core.rmem_max = 33554432
En el nivel de aplicación, hemos aumentado el tamaño del búfer de recepción:
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
Después de la llamada a getsockopt (), el valor impreso es siempre 2 veces el valor establecido (67108864 en el ejemplo anterior), pero creo que es de esperar.
Sé que el hecho de no consumir datos lo suficientemente rápido puede provocar la pérdida de paquetes. Sin embargo, todo lo que esta aplicación hace es verificar la secuencia y luego insertar los datos en una cola; el procesamiento real se realiza en otro hilo. Además, la máquina es moderna (doble Xeon X5560, 8 GB de RAM) y muy poco cargada. Tenemos literalmente docenas de aplicaciones idénticas que reciben datos a una velocidad mucho mayor que no experimentan este problema.
Además de una aplicación que consume demasiado lento, ¿hay otras razones por las cuales el kernel de Linux podría eliminar paquetes UDP?
FWIW, esto está en CentOS 4, con kernel 2.6.9-89.0.25.ELlargesmp.
int ret = setsockopt(my_socket_fd, SOL_SOCKET, SO_RCVBUF, (char *)&sockbufsize, (int)sizeof(sockbufsize));
En primer lugar, setsockopt
toma (int, int, int, void *, socklen_t), por lo que no se requieren conversiones.
Utilizando un simple sniffer de paquetes basado en libpcap, he determinado que no hay lagunas en los datos a nivel de hardware. Sin embargo, veo muchas lagunas en mi aplicación. Esto sugiere que el kernel está dejando caer paquetes;
Sugiere que su entorno no es lo suficientemente rápido. Se sabe que la captura de paquetes es un proceso intensivo, y observará que la tasa global de transmisiones en una interfaz disminuirá a medida que comience a capturar programas como iptraf-ng o tcpdump en uno.
Tuve un problema similar con mi programa. Su tarea es recibir paquetes udp en un hilo y, usando una cola de bloqueo, escribirlos en la base de datos con otro hilo.
Noté (usando vmstat 1
) que cuando el sistema estaba experimentando operaciones pesadas de espera de E / S (lecturas) mi aplicación no recibía paquetes, sin embargo los estaba recibiendo el sistema.
El problema era que, cuando se producía una gran espera de E / S, el hilo que estaba escribiendo en la base de datos estaba siendo bloqueado por E / S mientras se mantenía el mutex de la cola. De esta forma, el buffer udp estaba siendo sobrevolado por los paquetes entrantes, porque el hilo principal que los recibía estaba colgado en pthred_mutex_lock()
.
Lo resolví jugando con ioniceness (comando ionice
) de mi proceso y el proceso de la base de datos. Cambiar la clase de E / S de Best a Efficiency ayudó. Sorprendentemente, no puedo reproducir este problema ahora, incluso con la bondad de E / S por defecto. Mi kernel es 2.6.32-71.el6.x86_64.
Todavía estoy desarrollando esta aplicación, así que intentaré actualizar mi publicación una vez que sepa más.
No tengo suficiente reputación para comentar, pero similar a @racic, tenía un programa donde tenía un hilo de recepción y un hilo de procesamiento con una cola de bloqueo entre ellos. Noté el mismo problema con la caída de paquetes porque el hilo de recepción estaba esperando un bloqueo en la cola de bloqueo.
Para resolver esto, agregué un búfer local más pequeño al hilo de recepción, e hice que solo insertara datos en el búfer y luego no se bloqueó (usando std :: mutex :: try_lock).