¿Cómo monitorear el espacio disponible del buffer UDP de Linux?

Tengo una aplicación java en Linux que abre el socket UDP y espera mensajes.

Después de un par de horas bajo una gran carga, hay una pérdida de paquetes, es decir, los paquetes son recibidos por kernel pero no por mi aplicación (vemos los paquetes perdidos en sniffer, vemos paquetes UDP perdidos en netstat, no vemos esos paquetes en nuestros registros de aplicaciones).

Intentamos ampliar los buffers de socket, pero esto no ayudó, comenzamos a perder paquetes más tarde que antes, pero eso es todo.

Para la depuración, quiero saber cuán lleno está el buffer udp del SO, en cualquier momento dado. Busqué en Google, pero no encontré nada. ¿Me puedes ayudar?

PS Chicos, soy consciente de que UDP no es confiable. Sin embargo, mi computadora recibe todos los mensajes UDP, mientras que mi aplicación no puede consumir algunos de ellos. Quiero optimizar mi aplicación al máximo, ese es el motivo de la pregunta. Gracias.

Linux proporciona los archivos /proc/net/udp y /proc/net/udp6 , que enumera todos los sockets UDP abiertos (para IPv4 e IPv6, respectivamente). En ambos, las columnas tx_queue y rx_queue muestran las colas salientes y entrantes en bytes.

Si todo funciona como se espera, generalmente no verá ningún valor diferente a cero en esas dos columnas: tan pronto como su aplicación genere paquetes, se enviarán a través de la red y, tan pronto como lleguen esos paquetes desde la red, su aplicación se activará. y recv (la llamada recv vuelve inmediatamente). Puede ver que rx_queue suba si su aplicación tiene el socket abierto pero no está invocando recv para recibir los datos, o si no está procesando dichos datos lo suficientemente rápido.

UDP es un protocolo perfectamente viable. ¡Es el mismo viejo caso de la herramienta correcta para el trabajo correcto!

Si tiene un progtwig que espera datagtwigs UDP, y luego se apaga para procesarlos antes de volver a esperar otro, entonces su tiempo de procesamiento transcurrido debe ser siempre más rápido que el peor índice de llegada de datagtwigs. Si no es así, la cola de recepción del socket UDP comenzará a llenarse.

Esto puede ser tolerado por ráfagas cortas. La cola hace exactamente lo que se supone que debe hacer: poner los datagtwigs en cola hasta que esté listo. Pero si la tasa de llegada promedio regularmente causa un retraso en la cola, es hora de rediseñar su progtwig. Aquí hay dos opciones principales: reducir el tiempo de procesamiento transcurrido a través de técnicas de progtwigción astutas, y / o multi-hilo de su progtwig. También se puede emplear el equilibrio de carga en varias instancias de su progtwig.

Como se mencionó anteriormente, en Linux puede examinar el sistema de archivos proc para obtener el estado de UDP. Por ejemplo, si /proc/net/udp nodo /proc/net/udp , obtengo algo como esto:

 $ cat /proc/net/udp sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode ref pointer drops 40: 00000000:0202 00000000:0000 07 00000000:00000000 00:00000000 00000000 0 0 3466 2 ffff88013abc8340 0 67: 00000000:231D 00000000:0000 07 00000000:0001E4C8 00:00000000 00000000 1006 0 16940862 2 ffff88013abc9040 2237 122: 00000000:30D4 00000000:0000 07 00000000:00000000 00:00000000 00000000 1006 0 912865 2 ffff88013abc8d00 0 

A partir de esto, puedo ver que un socket propiedad de la identificación de usuario 1006, está escuchando en el puerto 0x231D (8989) y que la cola de recepción está a unos 128 KB. Como 128 KB es el tamaño máximo en mi sistema, esto me dice que mi progtwig es lamentablemente débil para mantenerse al día con los datagtwigs que llegan. Hasta el momento, se han producido 2237 caídas, lo que significa que la capa UDP no puede poner más datagtwigs en la cola de los sockets, y debe soltarlos.

Puede observar el comportamiento de su progtwig a lo largo del tiempo, por ejemplo, al usar:

 watch -d 'cat /proc/net/udp|grep 00000000:231D' 

Tenga en cuenta también que el comando netstat hace más o menos lo mismo: netstat -c --udp -an

Mi solución para mi progtwig weenie será multihilo.

¡Aclamaciones!

rx_queue te dirá la longitud de la cola en un instante dado, pero no te dirá qué tan completa ha sido la cola, es decir, la marca de agua alta. No hay forma de controlar constantemente este valor, y no hay forma de obtenerlo mediante progtwigción (consulte ¿Cómo obtengo la cantidad de datos en cola para el socket UDP? ).

La única forma en que puedo imaginarme monitoreando la longitud de la cola es mover la cola a tu propio progtwig. En otras palabras, inicie dos hilos: uno lee el zócalo lo más rápido posible y descarga los datagtwigs en su cola; y el otro es su progtwig que extrae de esta cola y procesa los paquetes. Por supuesto, esto supone que puede asegurar que cada hilo está en una CPU separada. Ahora puede monitorear la longitud de su propia cola y realizar un seguimiento de la marca Highwater.

El proceso es simple:

  1. Si lo desea, detenga el proceso de solicitud.

  2. Abra el socket UDP. Puede engancharlo del proceso en ejecución usando /proc//fd si es necesario. O puede agregar este código a la aplicación y enviarle una señal: ya tendrá el socket abierto, por supuesto.

  3. Llame a recvmsg en un circuito cerrado lo más rápido posible.

  4. Cuente cuántos paquetes / bytes tiene.

Esto descartará cualquier datagtwig almacenado actualmente, pero si eso rompe su aplicación, su aplicación ya estaba rota.