¡Rutinas de resolución de problemas en línea de JAVA, desde CPU, disco, memoria, red hasta GC todo en uno!

Las fallas en línea incluyen principalmente problemas de cpu, disco, memoria y red, y la mayoría de las fallas pueden contener más de un nivel de problemas, por lo tanto, al solucionar problemas, intente verificar los cuatro aspectos uno por uno.

Al mismo tiempo, herramientas como jstack y jmap no se limitan a un aspecto del problema. Básicamente, el problema es df, free y top, y luego jstack y jmap se sirven en secuencia. Los problemas específicos se pueden analizar en detalle.

UPC

En términos generales, primero solucionaremos los problemas de la CPU. las excepciones de la CPU suelen estar mejor ubicadas. Las razones incluyen problemas de lógica empresarial (bucle sin fin), gc frecuente y cambios de contexto excesivos. Y lo más común a menudo es causado por la lógica empresarial (o lógica de marco), puede usar jstack para analizar la situación de pila correspondiente.

Utilice jstack para analizar los problemas de la CPU

Primero usamos el comando ps para encontrar el pid del proceso correspondiente (si tiene varios procesos de destino, puede usar top para ver cuál ocupa más alto).

Luego use top -H -p pid para encontrar algunos subprocesos con un alto uso de cpu

¡Rutinas de resolución de problemas en línea de JAVA, desde CPU, disco, memoria, red hasta GC todo en uno!

Luego convierta el pid más alto a hexadecimal para printf '%x\n' pidobtener nid

¡Rutinas de resolución de problemas en línea de JAVA, desde CPU, disco, memoria, red hasta GC todo en uno!

Luego encuentre la información de la pila correspondiente directamente en jstackjstack pid |grep 'nid' -C5 –color

¡Rutinas de resolución de problemas en línea de JAVA, desde CPU, disco, memoria, red hasta GC todo en uno!

Puede ver que hemos encontrado la información de la pila con nid 0x42, y luego solo necesitamos analizarla cuidadosamente.

Por supuesto, es más común que analicemos el archivo jstack completo. Por lo general, prestaremos más atención a las partes WAITING y TIMED_WAITING, y no hace falta decir BLOCKED. Podemos usar comandos cat jstack.log | grep "java.lang.Thread.State" | sort -nr | uniq -cpara tener una idea general del estado de jstack, si hay demasiados EN ESPERA, probablemente haya un problema.

¡Rutinas de resolución de problemas en línea de JAVA, desde CPU, disco, memoria, red hasta GC todo en uno!

GC frecuente

Por supuesto, todavía usaremos jstack para analizar el problema, pero a veces podemos determinar primero si el gc es demasiado frecuente y usar el comando jstat -gc pid 1000 para observar los cambios en la generación gc. 1000 representa el intervalo de muestreo (ms), S0C / S1C, S0U / S1U, EC / EU, OC / OU, MC / MU representan la capacidad y el uso de las dos áreas Survivor, el área Eden, la vejez y el área de metadatos, respectivamente. YGC / YGT, FGC / FGCT y GCT representan el tiempo, la frecuencia y el tiempo total consumido por YoungGc y FullGc. Si ve que gc es más frecuente, realice un análisis más detallado de gc.

¡Rutinas de resolución de problemas en línea de JAVA, desde CPU, disco, memoria, red hasta GC todo en uno!

Cambio de contexto

Para problemas de contexto frecuentes, podemos usar el comando vmstat para ver

¡Rutinas de resolución de problemas en línea de JAVA, desde CPU, disco, memoria, red hasta GC todo en uno!

La columna cs (cambio de contexto) representa el número de cambios de contexto.

Si queremos monitorear un pid específico, podemos usar el comando pidstat -w pid, cswch y nvcswch indican conmutación voluntaria e involuntaria.

¡Rutinas de resolución de problemas en línea de JAVA, desde CPU, disco, memoria, red hasta GC todo en uno!

Disco

Los problemas de disco son más básicos, como la CPU. El primero es el espacio en disco, usamos directamente df -hl para ver el estado del sistema de archivos

¡Rutinas de resolución de problemas en línea de JAVA, desde CPU, disco, memoria, red hasta GC todo en uno!

Más a menudo, el problema del disco sigue siendo un problema de rendimiento. Podemos analizar por iostatiostat -d -k -x

¡Rutinas de resolución de problemas en línea de JAVA, desde CPU, disco, memoria, red hasta GC todo en uno!

La última columna% util puede ver el grado de escritura en cada disco, mientras que rrqpm / sy wrqm / s representan las velocidades de lectura y escritura respectivamente, lo que generalmente puede ayudar a localizar el disco específico que tiene un problema.

Además, también necesitamos saber qué proceso está leyendo y escribiendo.En términos generales, el desarrollador lo conoce bien o usa el comando iotop para localizar la fuente de lectura y escritura del archivo.

¡Rutinas de resolución de problemas en línea de JAVA, desde CPU, disco, memoria, red hasta GC todo en uno!

Pero lo que tenemos aquí es tid, necesitamos convertirlo a pid, podemos encontrar pidreadlink -f /proc/*/task/tid/../ .. a través de readlink.

¡Rutinas de resolución de problemas en línea de JAVA, desde CPU, disco, memoria, red hasta GC todo en uno!

Después de encontrar el pid, puede ver las condiciones específicas de lectura y escritura de este proceso cat / proc / pid / io

¡Rutinas de resolución de problemas en línea de JAVA, desde CPU, disco, memoria, red hasta GC todo en uno!

También podemos usar el comando lsof para determinar las condiciones específicas de lectura y escritura del archivo lsof -p pid

¡Rutinas de resolución de problemas en línea de JAVA, desde CPU, disco, memoria, red hasta GC todo en uno!

RAM

Los problemas de memoria son más problemáticos que la CPU, y hay más escenarios. Incluye principalmente problemas de OOM, GC y memoria fuera del montón. En términos generales, primero usaremos el comando libre para verificar las diversas condiciones de la memoria de un disparo.

¡Rutinas de resolución de problemas en línea de JAVA, desde CPU, disco, memoria, red hasta GC todo en uno!

Memoria del montón

La mayoría de los problemas de memoria siguen siendo problemas de memoria acumulada. Se divide principalmente en OOM y StackOverflow.

TÍO

Memoria insuficiente en JMV, OOM se puede dividir aproximadamente en los siguientes tipos:

Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread

Esto significa que no hay suficiente espacio de memoria para asignar la pila de Java al hilo. Básicamente, todavía hay un problema con el código del grupo de hilos, como olvidar cerrar, por lo que primero debemos buscar el problema desde el nivel de código, usando jstack o jmap. Si todo es normal, la JVM puede reducir el tamaño de una sola pila de subprocesos especificando Xss.

Además, a nivel del sistema, puede aumentar el límite de subprocesos del sistema operativo modificando /etc/security/limits.confnofile y nproc

¡Rutinas de resolución de problemas en línea de JAVA, desde CPU, disco, memoria, red hasta GC todo en uno!

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

Esto significa que el uso de memoria del montón ha alcanzado el valor máximo establecido por -Xmx, que debería ser el error OOM más común. La solución sigue siendo encontrarlo primero en el código. Si hay una pérdida de memoria, use jstack y jmap para localizar el problema. Si todo es normal, debe ajustar el valor de Xmx para expandir la memoria.

Caused by: java.lang.OutOfMemoryError: Meta space

Esto significa que el uso de memoria del área de metadatos ha alcanzado el valor máximo establecido por XX: MaxMetaspaceSize. La idea de solución de problemas es la misma que la anterior. Los parámetros se pueden ajustar a través de XX: MaxPermSize (sin mencionar la generación permanente antes de 1.8).

Desbordamiento de pila

La memoria de la pila se desborda y todos ven más de esto.

Exception in thread "main" java.lang.StackOverflowError

Indica que la memoria requerida por la pila de subprocesos es mayor que el valor de Xss, y también se verifica primero Los parámetros se ajustan a través de Xss, pero un ajuste demasiado grande puede causar OOM.

Utilice JMAP para localizar fugas de memoria de código

Para la investigación de código anterior en OOM y StackOverflow, generalmente usamos JMAPjmap -dump: format = b, file = filename pid para exportar el archivo de volcado

¡Rutinas de resolución de problemas en línea de JAVA, desde CPU, disco, memoria, red hasta GC todo en uno!

Importe el archivo de volcado a través de mat (Eclipse Memory Analysis Tools) para su análisis. Generalmente, podemos seleccionar directamente Leak Suspects para las fugas de memoria. Mat da sugerencias sobre las fugas de memoria. También puede elegir Principales consumidores para ver el informe de objetos más grande. Las preguntas relacionadas con los hilos se pueden analizar seleccionando la descripción general del hilo. Además, elija la descripción general de la clase Histograma para analizarla usted mismo lentamente. Puede buscar tutoriales relacionados en el tapete.

¡Rutinas de resolución de problemas en línea de JAVA, desde CPU, disco, memoria, red hasta GC todo en uno!

En el desarrollo diario, las fugas de memoria en el código son relativamente comunes y están relativamente ocultas, lo que requiere que los desarrolladores presten más atención a los detalles. Por ejemplo, cada solicitud es un objeto nuevo, lo que resulta en una gran cantidad de creación de objetos repetidos; las operaciones de flujo de archivos se realizan pero no se cierran correctamente; activación manual incorrecta de gc; la asignación de caché ByteBuffer irrazonable provocará el código OOM.

Por otro lado, podemos especificar en los parámetros de inicio -XX:+HeapDumpOnOutOfMemoryErrorpara guardar el archivo de volcado durante OOM.

problemas e hilos de gc

El problema de gc no solo afecta a la CPU, sino que también afecta a la memoria, las ideas para la solución de problemas también son las mismas. Generalmente, use jstat primero para verificar los cambios generacionales, como si hay demasiados tiempos de youngGC o fullGC; si el crecimiento de indicadores como EU y OU es anormal.

Si hay demasiados subprocesos y no a tiempo, gc también causará oom, la mayoría de los cuales son los mencionados anteriormente "no se puede crear un nuevo subproceso nativo". Además del análisis detallado del archivo de volcado por jstack, generalmente miramos primero el hilo general, a través de pstreee -p pid | wc -l.

¡Rutinas de resolución de problemas en línea de JAVA, desde CPU, disco, memoria, red hasta GC todo en uno!

O directamente viendo el número de / proc / pid / task es el número de hilos.

¡Rutinas de resolución de problemas en línea de JAVA, desde CPU, disco, memoria, red hasta GC todo en uno!

Memoria fuera del montón

Sería realmente desafortunado si se encuentra con un desbordamiento de memoria sin pila. En primer lugar, el desbordamiento de memoria fuera del montón se manifiesta por el rápido crecimiento de la memoria física residente. Si se informa un error, depende del método de uso. Si se debe al uso de Netty, puede aparecer un error OutOfDirectMemoryError en el registro de errores. Si es DirectByteBuffer directamente, se informará OutOfMemoryError: Direct buffer memory.

El desbordamiento de memoria fuera del montón a menudo está relacionado con el uso de NIO. Generalmente, primero usamos pmap para ver la memoria ocupada por el proceso pmap -x pid | sort -rn -k3 | head -30, esta sección significa ver los primeros 30 del pid correspondiente en orden inverso Gran segmento de memoria. Aquí puede ejecutar el comando nuevamente después de un tiempo para ver el crecimiento de la memoria, o dónde el segmento de memoria es sospechoso en comparación con la máquina normal.

¡Rutinas de resolución de problemas en línea de JAVA, desde CPU, disco, memoria, red hasta GC todo en uno!

Si determinamos que hay un final de memoria sospechoso, necesitamos analizar gdb a través de gdb --batch --pid {pid} -ex "dump memory filename.dump {dirección de inicio de memoria} {dirección de inicio de memoria + tamaño de bloque de memoria}"

¡Rutinas de resolución de problemas en línea de JAVA, desde CPU, disco, memoria, red hasta GC todo en uno!

Después de obtener el archivo de volcado, puede usar heaxdump para verlo hexdump -C filename | less, pero la mayoría de lo que ve son caracteres binarios ilegibles.

NMT es una nueva función de HotSpot introducida por Java7U40. Con el comando jcmd, podemos ver la composición específica de la memoria. Es necesario agregarlo a los parámetros de inicio  -XX:NativeMemoryTracking=summary o  -XX:NativeMemoryTracking=detailhabrá una ligera pérdida de rendimiento.

Generalmente, para la situación en la que la memoria fuera del montón crece lentamente hasta explotar, se puede establecer primero una línea de base jcmd pid VM.native_memory.

¡Rutinas de resolución de problemas en línea de JAVA, desde CPU, disco, memoria, red hasta GC todo en uno!

Luego, espere un período de tiempo para ver el crecimiento de la memoria y haga un resumen o diferencia de nivel de detalle a través de jcmd pid VM.native_memory detail.diff (summary.diff).

¡Rutinas de resolución de problemas en línea de JAVA, desde CPU, disco, memoria, red hasta GC todo en uno!

¡Rutinas de resolución de problemas en línea de JAVA, desde CPU, disco, memoria, red hasta GC todo en uno!

Puede ver que la memoria analizada por jcmd es muy detallada, incluido el montón, el hilo y gc (por lo que las otras excepciones de memoria mencionadas anteriormente pueden ser analizadas por nmt). Aquí nos enfocamos en el crecimiento de la memoria interna, si el aumento es muy obvio Si es así, hay un problema.

En el nivel de detalle, habrá un crecimiento de segmentos de memoria específicos, como se muestra en la figura siguiente.

¡Rutinas de resolución de problemas en línea de JAVA, desde CPU, disco, memoria, red hasta GC todo en uno!

Además, a nivel del sistema, también podemos usar el comando strace para monitorear la asignación de memoria strace -f -e "brk, mmap, munmap" -p pid

La información de asignación de memoria aquí incluye principalmente pid y dirección de memoria.

¡Rutinas de resolución de problemas en línea de JAVA, desde CPU, disco, memoria, red hasta GC todo en uno!

Sin embargo, es difícil localizar el problema específico con las operaciones anteriores. La clave es mirar la pila de registro de errores, encontrar el objeto sospechoso, averiguar su mecanismo de recuperación y luego analizar el objeto correspondiente. Por ejemplo, si DirectByteBuffer asigna memoria, se requiere GC completo o system.gc manual para reciclarlo (por lo que es mejor no usar -XX: + DisableExplicitGC).

De hecho, podemos rastrear la situación de la memoria del objeto DirectByteBuffer y activar manualmente fullGC a través de jmap -histo: live pid para ver si se ha reciclado la memoria fuera del montón. Si se reclama, existe una alta probabilidad de que la memoria fuera del montón se asigne demasiado pequeña, lo que puede ajustarse mediante -XX: MaxDirectMemorySize. Si no hay ningún cambio, utilice jmap para analizar aquellos objetos que no pueden ser gc y la relación de referencia con DirectByteBuffer.

Problemas de GC

Las pérdidas de memoria en el montón siempre van acompañadas de excepciones de GC. Sin embargo, los problemas de GC no solo están relacionados con problemas de memoria, sino que también pueden causar una serie de complicaciones, como la carga de la CPU y los problemas de red. Solo están relativamente relacionados con la memoria, por lo que aquí resumiremos por separado los problemas relacionados con GC.

En el capítulo de la CPU, presentamos el uso de jstat para obtener la información actual del cambio generacional de GC. Más a menudo, usamos el registro de GC para solucionar problemas y lo agregamos -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStampsa los parámetros de inicio para activar el registro de GC.

El significado de los registros comunes de Young GC y Full GC no se repetirá aquí.

Para el registro de gc, podemos inferir aproximadamente si el youngGC y el fullGC son demasiado frecuentes o tardan demasiado, para prescribir el medicamento correcto. Analizaremos el recolector de basura G1 a continuación. También se recomienda que utilice G1-XX: + UseG1GC.

youngGC demasiado frecuente

Los youngGC frecuentes suelen ser objetos pequeños de período corto. Primero, considere si la configuración del área del Edén / Cenozoico es demasiado pequeña y vea si el problema se puede resolver ajustando la configuración de parámetros como -Xmn y -XX: SurvivorRatio. Si los parámetros son normales, pero la frecuencia de gc joven aún es demasiado alta, debe usar Jmap y MAT para investigar más el archivo de volcado.

youngGC tarda demasiado

El problema del consumo excesivo de tiempo depende de qué parte del registro de GC requiera mucho tiempo. Tomando el registro G1 como ejemplo, puede concentrarse en el escaneo de raíz, la copia de objeto, el proceso de referencia y otras etapas. Ref Proc lleva mucho tiempo, así que preste atención a las referencias a objetos relacionados.

Root Scanning lleva mucho tiempo, así que preste atención al número de subprocesos y referencias de generación cruzada. La copia de objeto debe prestar atención al ciclo de vida del objeto. Y el análisis que requiere mucho tiempo requiere una comparación horizontal, es decir, una comparación que requiere mucho tiempo con otros proyectos o períodos de tiempo normales. Por ejemplo, si el análisis de raíces en la figura aumenta más que el período de tiempo normal, significa que hay demasiados hilos.

¡Rutinas de resolución de problemas en línea de JAVA, desde CPU, disco, memoria, red hasta GC todo en uno!

Gatillo fullGC

G1 es más de MixedGC, pero mixedGC se puede investigar de la misma manera que youngGC. Cuando se activa fullGC, generalmente habrá problemas. G1 se degenerará y usará el recolector serial para limpiar la basura. El tiempo de pausa llega al segundo nivel, que se puede decir que es medio arrodillado.

Las razones para fullGC pueden incluir lo siguiente, así como algunas ideas para el ajuste de parámetros:

  • Fallo de fase concurrente: en la fase de marcado concurrente, la generación anterior se llena antes de MixGC, luego G1 abandonará el ciclo de marcado en este momento. En este caso, puede ser necesario aumentar el tamaño del montón o ajustar el número de subprocesos de marcado simultáneos-XX: ConcGCThreads.
  • Fallo de promoción: no hay suficiente memoria para el objeto de supervivencia / promoción durante la GC, por lo que se activa la GC completa. En este momento, puede aumentar el porcentaje de memoria reservada a través de -XX: G1ReservePercent, reducir -XX: InitiatingHeapOccupancyPercent para iniciar la marca por adelantado, y -XX: ConcGCThreads para aumentar el número de subprocesos marcados también es posible.
  • Error de asignación de objetos grandes: los objetos grandes no pueden encontrar un espacio de región adecuado para la asignación y se ejecutará fullGC. En este caso, puede aumentar la memoria o aumentar -XX: G1HeapRegionSize.
  • El programa ejecuta activamente System.gc (): no lo escriba de forma casual.

Además, podemos configurar -XX: HeapDumpPath = / xxx / dump.hprof en los parámetros de inicio para volcar archivos relacionados con fullGC y usar jinfo para volcar antes y después de gc

jinfo -flag +HeapDumpBeforeFullGC pid 
jinfo -flag +HeapDumpAfterFullGC pid

De esta manera, se obtienen dos archivos de volcado Después de la comparación, el enfoque principal está en los objetos problemáticos que gc dejó caer para localizar el problema.

Busque almas gemelas de Java, responda a la "entrevista de fondo" y envíele un libro de entrevistas.pdf

La Internet

Los problemas relacionados con el nivel de la red son generalmente más complejos, con muchos escenarios y un posicionamiento difícil, lo que se ha convertido en una pesadilla para la mayoría de desarrollos, y debería ser el más complicado. Aquí le daré algunos ejemplos y explicará desde la capa tcp, la capa de aplicación y el uso de herramientas.

se acabó el tiempo

La mayoría de los errores de tiempo de espera se encuentran en el nivel de la aplicación, por lo que este se centra en comprender los conceptos. Los tiempos de espera se pueden dividir aproximadamente en tiempos de espera de conexión y tiempos de espera de lectura-escritura. Algunos marcos de cliente que utilizan grupos de conexiones también tienen tiempos de espera de adquisición de conexión y tiempos de espera de limpieza de conexión inactiva.

  • Tiempo de espera de lectura y escritura. readTimeout / writeTimeout, algunos marcos se denominan so_timeout o socketTimeout, ambos se refieren al tiempo de espera de lectura y escritura de datos. Tenga en cuenta que la mayoría de los tiempos de espera aquí se refieren a tiempos de espera lógicos. El tiempo de espera de soa también se refiere al tiempo de espera de lectura. Los tiempos de espera de lectura y escritura generalmente solo se establecen para el cliente.

  • Tiempo de conexión agotado. connectionTimeout, el cliente generalmente se refiere al tiempo máximo para establecer una conexión con el servidor. El connectionTimeout en el lado del servidor es un poco variado. Jetty representa el tiempo de limpieza de la conexión inactiva y tomcat representa el tiempo máximo que se mantiene la conexión.

  • otro. Incluyendo el tiempo de espera de adquisición de conexión connectionAcquireTimeout y el tiempo de espera de limpieza de conexión inactiva idleConnectionTimeout. Se utiliza principalmente para marcos de cliente o servidor que utilizan grupos de conexiones o colas.

Cuando establecemos varios tiempos de espera, debemos confirmar que intentamos mantener el tiempo de espera del cliente menor que el tiempo de espera del servidor para asegurarnos de que la conexión finaliza normalmente.

En el desarrollo real, lo que más nos importa debería ser el tiempo de espera de lectura y escritura de la interfaz.

Cómo establecer un tiempo de espera de interfaz razonable es un problema. Si el tiempo de espera de la interfaz se establece demasiado largo, puede ocupar demasiado la conexión TCP del servidor. Si la configuración de la interfaz es demasiado corta, el tiempo de espera de la interfaz será muy frecuente.

La interfaz del servidor obviamente reduce rt, pero el cliente aún mantiene el tiempo de espera es otro problema. Este problema es realmente muy simple: el enlace del cliente al servidor incluye transmisión de red, colas y procesamiento de servicios. Cada enlace puede ser una causa que lleve mucho tiempo.

Desbordamiento de la cola TCP

El desbordamiento de la cola de TCP es un error de nivel relativamente bajo, que puede provocar errores más superficiales, como tiempos de espera y primeros. Por lo tanto, el error está más oculto, así que hablemos de él por separado.

¡Rutinas de resolución de problemas en línea de JAVA, desde CPU, disco, memoria, red hasta GC todo en uno!

Como se muestra en la figura anterior, hay dos colas: cola syns (cola semi-conectada) y aceptar cola (cola completamente conectada). Apretón de manos de tres vías, después de que el servidor recibe la sincronización del cliente, coloca el mensaje en la cola de sincronización y responde con syn + ack al cliente. El servidor recibe la confirmación del cliente. Si la cola de aceptación no está llena en este momento, sacará el almacenamiento temporal de la cola de Syns. La información se coloca en la cola de aceptación; de lo contrario, se ejecuta como lo indica tcp_abort_on_overflow.

tcp_abort_on_overflow 0 significa que si la cola de aceptación está llena durante el tercer paso del protocolo de enlace de tres vías, el servidor desecha el ack enviado por el cliente. tcp_abort_on_overflow 1 significa que si la cola de conexión completa está llena en el tercer paso, el servidor envía un primer paquete al cliente, lo que indica que el proceso de reconocimiento y la conexión están abolidos, lo que significa que puede haber muchos restablecimientos de conexión / restablecimiento de conexión por parte de los pares en el registro.

Entonces, en el desarrollo real, ¿cómo podemos ubicar rápidamente el desbordamiento de la cola tcp?

comando netstat, ejecutarnetstat -s | egrep "listen|LISTEN"

¡Rutinas de resolución de problemas en línea de JAVA, desde CPU, disco, memoria, red hasta GC todo en uno!

Como se muestra en la figura anterior, desbordado indica el número de desbordamientos de la cola completamente conectada, y sockets caídos indica el número de desbordamientos de la cola semiconectada.

comando ss, ejecutar ss -lnt

¡Rutinas de resolución de problemas en línea de JAVA, desde CPU, disco, memoria, red hasta GC todo en uno!

Puede ver Send-Q arriba que el número máximo de colas completamente conectadas en el puerto de escucha en la tercera columna es 5, y la primera columna Recv-Q es cuánto está usando actualmente la cola completamente conectada.

Luego, veamos cómo establecer el tamaño de las colas completamente conectadas y semiconectadas:

El tamaño de la cola completamente conectada depende de min (backlog, somaxconn). La acumulación se pasa cuando se crea el socket, somaxconn es un parámetro del sistema a nivel del sistema operativo. El tamaño de la cola de semiconexión depende de max (64, / proc / sys / net / ipv4 / tcp_max_syn_backlog).

En el desarrollo diario, a menudo usamos el contenedor de servlets como servidor, por lo que a veces debemos prestar atención al tamaño de la cola de conexión del contenedor. El atasco en tomcat se llama acceptCount, y en jetty es acceptQueueSize.

Excepción RST

El paquete RST indica un restablecimiento de la conexión, que se utiliza para cerrar algunas conexiones inútiles. Por lo general, indica un cierre anormal, que es diferente de cuatro ondas de manos.

En el desarrollo real, a menudo vemos restablecimiento de conexión / restablecimiento de conexión por errores de pares, que son causados ​​por el paquete RST.

El puerto no existe

Si se envía una solicitud SYN para establecer una conexión como un puerto que no existe, el servidor devolverá directamente un mensaje RST para interrumpir la conexión si encuentra que no tiene este puerto.

Termine activamente la conexión en lugar de FIN

En términos generales, el cierre normal de la conexión debe lograrse a través de mensajes FIN, pero también podemos usar mensajes RST en lugar de FIN, lo que significa terminar la conexión directamente. En el desarrollo real, puede establecer el valor de SO_LINGER para controlar. Esto a menudo es deliberado, para omitir TIMED_WAIT, para proporcionar eficiencia interactiva y usarlo con precaución.

Se produce una excepción en un lado del cliente o servidor, y el otro lado envía un RST para informar a la conexión que se cierre

El desbordamiento de la cola tcp que mencionamos anteriormente para enviar paquetes RST en realidad pertenece a este tipo. A menudo, esto se debe a algunas razones, una de las partes ya no puede procesar la conexión de solicitud (por ejemplo, el programa se bloquea, la cola está llena) y se notifica a la otra parte que cierre la conexión.

El paquete TCP recibido no está en una conexión TCP conocida

Por ejemplo, si a la máquina de una parte le falta un paquete TCP debido a una red defectuosa, la otra parte cierra la conexión y luego recibe el paquete TCP faltante después de mucho tiempo, pero como la conexión TCP correspondiente ya no existe, enviará una directamente Paquete RST para abrir una nueva conexión.

Una parte no ha recibido el mensaje de confirmación de la otra parte durante mucho tiempo y envía un mensaje RST después de un cierto período de tiempo o tiempos de retransmisión

La mayor parte de esto también está relacionado con el entorno de red. Un entorno de red deficiente puede provocar más paquetes RST.

Dije antes que muchos mensajes RST harán que el programa informe errores. Una operación de lectura en una conexión cerrada informará el restablecimiento de la conexión, y una operación de escritura en una conexión cerrada informará el restablecimiento de la conexión por parte del par. Por lo general, también podemos ver errores de tubería rota. Este es un error a nivel de tubería. Significa leer y escribir en una tubería cerrada. A menudo es un error continuar leyendo y escribiendo datos después de recibir un RST y reportar un error de restablecimiento de conexión. También se introduce en los comentarios del código fuente de glibc.

¿Cómo determinamos la existencia del paquete RST al solucionar problemas? Por supuesto, use el comando tcpdump para capturar paquetes y use wirehark para un análisis simple. tcpdump -i en0 tcp -w xxx.cap, en0 representa la tarjeta de red de monitoreo.

¡Rutinas de resolución de problemas en línea de JAVA, desde CPU, disco, memoria, red hasta GC todo en uno!

A continuación, cuando abrimos el paquete capturado a través de wirehark, es posible que podamos ver la siguiente figura, la roja significa el paquete RST.

¡Rutinas de resolución de problemas en línea de JAVA, desde CPU, disco, memoria, red hasta GC todo en uno!

TIME_WAIT 和 CLOSE_WAIT

Creo que todo el mundo sabe lo que significan TIME_WAIT y CLOSE_WAIT.

Cuando estamos en línea, podemos usar directamente el comando netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'para ver el número de tiempo de espera y close_wait

Usar el comando ss será más rápidoss -ant | awk '{++S[$1]} END {for(a in S) print a, S[a]}'

¡Rutinas de resolución de problemas en línea de JAVA, desde CPU, disco, memoria, red hasta GC todo en uno!

TIEMPO DE ESPERA

La existencia de time_wait es para que el paquete de datos perdido sea reutilizado por la conexión subsiguiente, y la segunda es para cerrar la conexión normalmente dentro del rango de tiempo de 2MSL. Su existencia reducirá en gran medida la apariencia de los paquetes RST.

Es más probable que ocurra demasiado time_wait en escenarios con frecuentes conexiones cortas. En este caso, puede realizar algunos ajustes de parámetros del kernel en el servidor:

#表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭
net.ipv4.tcp_tw_reuse = 1
#表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭
net.ipv4.tcp_tw_recycle = 1

Por supuesto, no debemos olvidar el pozo del rechazo de paquetes de datos en el entorno NAT debido a marcas de tiempo incorrectas. Otra forma es cambiar tcp_max_tw_buckets. Cualquier time_wait que supere este número se eliminará, pero esto también dará como resultado el informe de desbordamiento de la tabla de depósitos de tiempo de espera. incorrecto.

CLOSE_WAIT

Close_wait a menudo se debe a problemas escritos por la aplicación y el mensaje FIN no se inicia nuevamente después del ACK. La probabilidad de close_wait es incluso mayor que la de time_wait y las consecuencias son más graves. A menudo se debe a que un lugar está bloqueado y la conexión no se cierra correctamente, lo que consume gradualmente todos los hilos.

Para localizar tales problemas, es mejor usar jstack para analizar la pila de subprocesos y solucionar el problema. Para más detalles, consulte los capítulos anteriores. He aquí solo un ejemplo.

Los estudiantes de desarrollo dijeron que CLOSE_WAIT siguió aumentando después de que la aplicación se puso en línea, hasta que colgó. Después de que jstack encontró la pila sospechosa, la mayoría de los subprocesos se atascaron en el método countdownlatch.await. Después de buscar a los estudiantes de desarrollo, se dieron cuenta de que se usaba subproceso múltiple, pero no fue así. Capture la excepción, la excepción que se encuentra después de la modificación es solo la clase más simple que no se encuentra y que a menudo aparece después de actualizar el SDK.

Supongo que te gusta

Origin blog.51cto.com/14957073/2542746
Recomendado
Clasificación