Problema
Muchas aplicaciones personalizadas llaman a los servicios web de AEM. Estas aplicaciones utilizan el cliente HTTP de Apache Commons u otras bibliotecas. Cuando los sistemas back-end experimentan problemas de rendimiento, AEM experimenta tiempos de respuesta lentos. Además, si demasiado subprocesos dejan de responder, puede llevar a una ralentización de la recopilación de residuos de JVM, a errores de memoria, agotamiento de los subprocesos del sistema operativo, etc.
Cuando se registran volcados de subprocesos o de montículos de AEM, se observan muchos subprocesos esperando las llamadas del servicio web.
Ejemplo de escenario:
a continuación [1], hay un ejemplo del seguimiento de pila de un volcado de subprocesos de JVM. Se ha registrado desde una instancia de AEM con una aplicación que estaba registrando un funcionamiento de servicio de back-end malo.
El volcado de subprocesos mostró algunos problemas:
- El subproceso de solicitud que se muestra a continuación estaba atascado esperando en un servicio web que no estaba respondiendo. No se estableció un tiempo de espera de lectura de socket, por lo que el subproceso estaba esperando siempre. Vea aquí la solución.
- Cientos de subprocesos estaban esperando en el subproceso de solicitud única. Esto se debía a que el grupo de subprocesos estaba configurado para que fuera único, el primero en entrar y el primero en salir. Tener tantos subprocesos pendientes causó una alta utilización de la memoria. Vea aquí la solución.
- El servicio web al que se estaba llamando estaba tardando demasiado en responder. Esto hizo que el subproceso mencionado se apilara.
Tenga en cuenta las líneas de pila resaltadas:
- En amarillo, puede ver que la aplicación personalizada está utilizando la biblioteca RestTemplate de Spring Framework para realizar una llamada de servicio web.
- En naranja, puede ver que Spring Framework utiliza el cliente HTTP de Apache Commons para sus llamadas de servicio web.
- En rojo, puede ver que el subproceso estaba atascado en SocketInputStream.socketRead, lo que significa que está esperando una respuesta en el servicio web.
[1]
Causa
A continuación se presentan algunas causas comunes:
- El host del servicio web es inaccesible y el socket de tiempo de espera de conexión no está configurado o está configurado por demasiado tiempo (por ejemplo, 10 minutos).
- El servicio web está activo, pero está respondiendo con un error que no está siendo administrado por la aplicación.
- El servicio web está activo, pero responde demasiado lento o no responde durante la respuesta. El socket “tiempo de espera de lectura” no está configurado o lo está demasiado tiempo. Los subprocesos esperan indefinidamente una respuesta.
- El grupo de procesos está configurado para permitir una solicitud de una en una. Esto hace que los subprocesos de solicitud concurrentes esperen.
Resolución
Las soluciones a estos problemas son las siguientes:
- Establezca el tiempo de espera de conexión a un valor razonable, por ejemplo, 3 segundos.
- Establezca el tiempo de espera de lectura a un valor razonable. Este valor depende del tiempo de espera que tarden las respuestas. Para la mayoría de los servicios web pequeños, 10 segundos es razonable. Sin embargo, algunos servicios web que procesan o envían y reciben archivos de gran tamaño requieren una configuración de tiempo de espera de lectura más alta.
- Consulte la documentación de su biblioteca de cliente httpclient o cliente de servicio web para saber cómo administrar el subprocesamiento múltiple de forma eficiente. Por ejemplo, en el cliente HTTP de Apache Commons 3.x, puede consultar esta página.
- Cachear las respuestas de las llamadas de servicio. Esto se aplica cuando se llama al servicio utilizando los mismos parámetros y se recibe el mismo resultado más de una vez.
- Si los datos son compartidos (no específicos del usuario), entonces considere llamar al servicio web con anticipación en un hilo de fondo y guarde el resultado para su uso posterior. Por ejemplo, usar un sling job, sling scheduler o Importador de encuestas de AEM para gestionar un subproceso de fondo.
- Si tiene un alto volumen de llamadas salientes, implementar back-off algorithm para tratar los fallos. Aquí es donde cuando la aplicación llama al servicio y falla X veces, entonces usted deja de intentarlo por un cierto tiempo e inmediatamente informa de los errores en su lugar. Luego intente X veces de nuevo y si falla o se agota de nuevo espere un tiempo más largo y así sucesivamente. Esto se hace generalmente con un aumento exponencial en el tiempo de espera con un tiempo límite máximo (también conocido como algoritmo de retroceso exponencial truncado).