Tengo una aplicación que se está quedando sin descriptores de archivo, aparentemente al abrir sockets, pero no puedo averiguar exactamente qué hacen estos sockets. Estos aparecen en la salida de lsof como
java 9689 appuser 1010u sock 0,5 263746675 can't identify protocol
java 9689 appuser 1011u sock 0,5 263746676 can't identify protocol
java 9689 appuser 1012u sock 0,5 263746677 can't identify protocol
java 9689 appuser 1014u sock 0,5 263746678 can't identify protocol
java 9689 appuser 1015u sock 0,5 263746679 can't identify protocol
java 9689 appuser 1016u sock 0,5 263746681 can't identify protocol
y en / proc / $ PID / fd como
lrwx------ 1 appuser appuser 64 Jun 23 11:49 990 -> socket:[263732085]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 991 -> socket:[263732086]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 992 -> socket:[263735307]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 993 -> socket:[263732088]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 995 -> socket:[263735308]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 996 -> socket:[263735309]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 997 -> socket:[263745434]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 998 -> socket:[263745435]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 999 -> socket:[263745436]
pero no hay salida similar en netstat -a
.
¿Qué son estos enchufes y cómo puedo averiguar qué hacen?
Editar : He intentado ejecutar grep $SOCKET /proc/net
, como se recomienda en las preguntas frecuentes de lsof , donde $ SOCKET es, por ejemplo, 263746679, pero tampoco dio resultados.
Como fondo, la aplicación es un contenedor para múltiples tareas que, entre otras, realizan llamadas de red. Necesito seleccionar el que se vuelve loco, pero hasta que descubra con quién se comunican esos enchufes, estoy atascado.
Respuestas:
Esto puede ocurrir si crea un socket, pero nunca se conecta () o enlaza () con él. Su mejor opción puede ser estratificar (-fF) la aplicación y luego hacer una referencia cruzada con la salida de lsof para determinar qué enchufes están causando el problema. Como método adicional de depuración: si envuelve sus llamadas de socket con información de depuración y las escribe en / dev / null, aparecerá en orden sin darle archivos de registro hilarantemente grandes.
fuente
Usando Python, he encontrado el mismo problema en los sockets SSL:
La solución fue desenvolver la capa SSL antes de cerrar:
Esto cierra los enchufes correctamente en mi aplicación.
fuente
Lo primero que haría es aumentar si el límite de su descriptor de archivo:
A continuación, me aseguraría de que su sistema esté actualizado, esto incluye todas las bibliotecas y servidores. Es posible que su servidor de aplicaciones Java esté desactualizado (si está usando uno). También es una posibilidad que su servidor de aplicaciones esté mal configurado, debe mirar su archivo de configuración y bajar su
connectionTimeout
y / o sumaxKeepAliveRequests
(no estoy seguro de qué servidor de aplicaciones está usando o si está usando uno ...).No estoy seguro de lo que hace esta aplicación, pero si no crees que requiere decenas de miles de sockets, entonces es casi seguro que "fuga de descriptor de archivo" en su aplicación Java. Es posible que deba enviar un informe de error al proveedor. En este informe de error, debe incluir información sobre cómo volver a crear el problema.
Aquí hay algunas formas de depurar el problema.
Wireshark (o twireshark para el cli) es la mejor herramienta para ver cómo se utilizan estos enchufes. Wireshark le dará un desglose del tipo de tráfico que se lanza por el cable. Es probable que las primeras conexiones tengan éxito y luego lleguen al límite del descriptor de archivo. Una vez que se alcanza el límite del descriptor de archivos, Wireshark no va a detectar nada (y más limpio es netstat para el caso), pero esto ayudará a reducir el problema. Puede haber un caso en el que se envíen muchos SYN salientes, sin embargo, no se reciben SYN / ACK, por lo que muchas conexiones tcp simplemente se atascan en el estado SYN_WAIT.
Si tiene acceso al código fuente y sabe el tipo de sockets que se crean (como usar strace o simplemente buscar el código), puede abrir el proyecto en Eclipse (u otro IDE) y establecer un punto de interrupción en la función que está creando estos enchufes. Cuando se alcanza el punto de interrupción, puede ver el seguimiento de la pila. Esta fuga del descriptor de archivo puede ser un simple bucle infinito o tal vez el valor de tiempo de espera del socket es demasiado grande. Otra posibilidad es que la aplicación Java no esté haciendo una
socket.close()
limpieza de las conexiones. Hacer un cierre se hace comúnmente en elfinely
bloque de untry/catch
(Sí, un socket siempre debe tener un try / catch en Java o no se compilará :). Al final del día, es probable que la aplicación Java no esté manejando sus IOException correctamente.fuente