Soluciona problemas de latencia elevada en las apps de App Engine

En muchos casos, la latencia elevada en la aplicación dará como resultado errores de servidor 5xx. Debido a que la causa raíz del error y los aumentos repentinos de latencia pueden ser las mismas, aplica las siguientes estrategias para solucionar problemas de latencia:

  1. Dimensiona el problema de latencia
  2. Identifica la causa
  3. Solucionar problemas

Determina el alcance del problema de latencia

Para definir el alcance del problema, haz las siguientes preguntas:

  • ¿A qué aplicaciones, servicios y versiones afecta este problema?
  • ¿A qué extremos específicos del servicio afecta este problema?
  • ¿Esto afecta a todos los clientes a nivel global o a un subconjunto específico de clientes?
  • ¿Cuál es la hora de inicio y de finalización del incidente? Considera especificar la zona horaria.
  • ¿Cuáles son los errores específicos?
  • ¿Cuál es la delta de latencia observada, que por lo general se especifica como un aumento en un percentil específico? Por ejemplo, la latencia aumentó 2 segundos en el percentil 90.
  • ¿Cómo mediste la latencia? En particular, ¿la midiste en el cliente o es visible en Cloud Logging o en los datos de latencia de Cloud Monitoring que proporciona la infraestructura de entrega de App Engine?
  • ¿Cuáles son las dependencias de tu servicio y alguna de ellas experimentó incidentes?
  • ¿Realizaste algún cambio reciente en el código, la configuración o la carga de trabajo que haya activado este problema?

Un servicio puede tener su propia supervisión y registro personalizados que puedes usar para limitar aún más el alcance del problema. Definir el alcance del problema te guiará hacia la causa raíz probable y determinará tus próximos pasos para solucionar problemas.

Identifica la causa

Determina qué componente de la ruta de la solicitud es más probable que cause la latencia o los errores. Los componentes principales de la ruta de solicitud son los siguientes:

Cliente --> Internet --> Google Front End (GFE) --> Infraestructura de entrega de App Engine --> Instancia de servicio

Si la información anterior no te dirige a la fuente de la falla, aplica las siguientes estrategias mientras revisas el estado y el rendimiento de la instancia de tu servicio:

  1. Supervisa los registros de solicitudes de App Engine. Si ves errores de código de estado HTTP o latencia elevada en esos registros, es probable que el problema se encuentre en la instancia que ejecuta tu servicio.

  2. Si la cantidad de instancias de servicio no aumentó para coincidir con los niveles de tráfico, es posible que tus instancias estén sobrecargadas, lo que genera errores y latencia elevados.

  3. Si ves errores elevados o latencia en Cloud Monitoring, es posible que el problema esté en sentido ascendente del balanceador de cargas, que registra las métricas de App Engine. En la mayoría de los casos, esto genera un problema en las instancias de servicio.

  4. Si ves una latencia elevada o errores en las métricas de supervisión, pero no en los registros de solicitudes, significa que se produjo una falla de balanceo de cargas o una falla grave de la instancia que impide que el balanceador de cargas enrute las solicitudes. Para distinguir entre estos casos, consulta los registros de solicitud antes de que comience el incidente. Si los registros de solicitud muestran una latencia creciente antes de la falla, significa que las instancias de la aplicación estaban empezando a fallar antes de que el balanceador de cargas dejara de enrutar las solicitudes a ellas.

Solucionar problemas

En esta sección, se describen las estrategias de solución de problemas de latencia elevada de los siguientes componentes de la ruta de la solicitud:

  1. Internet
  2. Google Front End (GFE)
  3. Infraestructura de entrega de App Engine
  4. Instancia de la aplicación
  5. Dependencias de aplicaciones

Internet

Es posible que tu aplicación tenga problemas de latencia debido a una conectividad deficiente o a un ancho de banda más bajo.

Conexión a Internet deficiente

Para determinar si el problema es de conectividad de Internet deficiente, ejecuta el siguiente comando en tu cliente:

$ curl -s -o /dev/null -w '%{time_connect}\n' <hostname>

El valor de time_connect representa la latencia de la conexión del cliente al Google Front End más cercano. Para conexiones lentas, sigue solucionando problemas con traceroute para determinar qué salto en la red causa la demora.

Ejecuta pruebas desde clientes en diferentes ubicaciones geográficas. App Engine enruta automáticamente las solicitudes al centro de datos de Google más cercano, que varía según la ubicación del cliente.

Ancho de banda bajo

Es posible que la aplicación responda con rapidez. Sin embargo, los cuellos de botella de la red retrasan la infraestructura de entrega de App Engine para que no envíe paquetes a través de la red con rapidez, lo que ralentiza las respuestas.

Google Front End (GFE)

Es posible que tu aplicación tenga problemas de latencia debido a un enrutamiento incorrecto, solicitudes simultáneas enviadas desde clientes HTTP/2 o la terminación de conexiones SSL.

Asigna una IP de cliente a una región geográfica

Google resuelve el nombre de host de la aplicación de App Engine en el GFE más cercano al cliente, según la dirección IP del cliente que se usa en la búsqueda de DNS. Si el agente de resolución de DNS del cliente no usa el protocolo EDNS0, es posible que Google no enrute las solicitudes del cliente al GFE más cercano.

Bloqueo de líneas de HTTP/2

Los clientes de HTTP/2 que envían varias solicitudes en paralelo pueden ver una latencia elevada debido al bloqueo de línea en el GFE. Para resolver este problema, los clientes deben usar el protocolo QUIC.

Terminación SSL para dominios personalizados

Es posible que GFE finalice la conexión SSL. Si usas un dominio personalizado en lugar de un dominio appspot.com, la finalización de SSL requiere un salto adicional. Esto podría agregar latencia para aplicaciones que se ejecutan en algunas regiones. Para obtener más información, consulta Asigna dominios personalizados.

Infraestructura de entrega de App Engine

Es posible que veas una latencia elevada en tu aplicación debido a incidentes en todo el servicio o al escalamiento automático.

Incidentes de todo el servicio

Google publica detalles de un error grave en todo el servicio en el panel Estado del servicio. Sin embargo, Google lanza las funciones de forma gradual, por lo que es poco probable que un incidente en todo el servicio afecte a todas tus instancias a la vez.

Ajuste de escala automático

La latencia elevada o los errores pueden deberse a las siguientes situaciones de escalamiento automático:

  • Escala el tráfico demasiado rápido: Es posible que el ajuste de escala automático de App Engine no escale tus instancias tan rápido como el tráfico aumente, lo que genera una sobrecarga temporal. Por lo general, la sobrecarga ocurre cuando un programa informático genera tráfico en lugar de los usuarios finales. Para resolver este problema, limita el sistema que genera el tráfico.

  • Aumentos repentinos de tráfico: Los aumentos repentinos de tráfico pueden causar una latencia elevada en casos en los que un servicio con ajuste de escala automático necesita escalar de forma vertical más rápido de lo posible sin afectar la latencia. El tráfico del usuario final no suele provocar aumentos repentinos frecuentes de tráfico. Si observas aumentos repentinos del tráfico, debes investigar la causa. Si un sistema por lotes se ejecuta a intervalos, tal vez puedas suavizar el tráfico o usar diferentes configuraciones de escalamiento.

  • Configuración del escalador automático: El escalador automático se puede configurar según las características de escalamiento de tu servicio. Los parámetros de escalamiento pueden volverse no óptimos en las siguientes situaciones:

    • La configuración de escalamiento del entorno estándar de App Engine puede causar latencia si se establece demasiado agresiva. Si ves respuestas del servidor con el código de estado 500 y el mensaje "Request was aborted after waiting too long to attempt to service your request" en tus registros, significa que se agotó el tiempo de espera de la solicitud en la fila pendiente mientras se esperaba una instancia inactiva.

    • Es posible que notes un aumento en el tiempo pendiente con el escalamiento manual, incluso cuando aprovisionas suficientes instancias. Te recomendamos que no uses el ajuste de escala manual si tu aplicación entrega tráfico de usuario final. El ajuste de escala manual es mejor para cargas de trabajo como las listas de tareas en cola.

    • La escalabilidad básica minimiza los costos a costa de la latencia. Te recomendamos que no uses el escalamiento básico para servicios sensibles a la latencia.

    • La configuración predeterminada del escalamiento de App Engine proporciona una latencia óptima para la mayoría de los servicios. Si aún ves solicitudes con un tiempo pendiente alto, especifica una cantidad mínima de instancias. Si ajustas la configuración de escalamiento para reducir costos mediante la minimización de instancias inactivas, corres el riesgo de ver aumentos repentinos de latencia si la carga aumenta de forma repentina.

Te recomendamos que compares el rendimiento con la configuración de escalamiento predeterminada y, luego, ejecutes una comparativa nueva después de cada cambio en esta configuración.

Implementaciones

La latencia elevada poco después de una implementación indica que no escalaste lo suficiente antes de migrar el tráfico. Es posible que las instancias más recientes no tengan cachés locales preparadas y se entreguen de manera más lenta que las instancias más antiguas.

Para evitar aumentos repentinos de latencia, no implementes un servicio de App Engine con el mismo nombre de versión que una versión existente del servicio. Si vuelves a usar un nombre de versión existente, no podrás migrar de forma lenta el tráfico a la versión nueva. Las solicitudes pueden ser más lentas porque App Engine reinicia cada instancia en un período corto. También tendrás que volver a implementar si deseas volver a la versión anterior.

Instancia de aplicación

En esta sección, se describen las estrategias comunes que puedes aplicar a las instancias de tu aplicación y al código fuente para optimizar el rendimiento y reducir la latencia.

Código de la aplicación

Los problemas en el código de la aplicación pueden ser muy difíciles de depurar, en especial si son intermitentes o no se pueden reproducir.

Para resolver los problemas, haz lo siguiente:

  • Para diagnosticar tus problemas, te recomendamos que instrumentes tu aplicación con registro, supervisión y seguimiento. También puedes usar Cloud Profiler.

  • Intenta reproducir el problema en un entorno de desarrollo local que podría permitirte ejecutar herramientas de depuración específicas del lenguaje que no son posibles para ejecutarlas en App Engine.

  • Para comprender mejor cómo falla la aplicación y qué cuellos de botella ocurren, prueba la aplicación hasta que falle. Establece un recuento máximo de instancias y, luego, aumenta de forma gradual la carga hasta que la aplicación falle.

  • Si el problema de latencia se correlaciona con la implementación de una versión nueva del código de tu aplicación, revierte la versión para determinar si la versión nueva causó el incidente. Sin embargo, si implementas de forma continua, las implementaciones frecuentes dificultan determinar si la implementación causó o no el incidente en función de la hora de inicio.

  • Tu aplicación puede almacenar parámetros de configuración dentro de Datastore o de otro lugar. Crea un cronograma de cambios de configuración para determinar si alguno de estos coincide con el inicio de la latencia elevada.

Cambio de la carga de trabajo

Un cambio de carga de trabajo puede causar una latencia elevada. Algunas métricas de supervisión que indican cambios en la carga de trabajo incluyen qps, el uso de la API y la latencia. Verifica también si hay cambios en los tamaños de solicitud y respuesta.

Presión de la memoria

Si la supervisión muestra un patrón de otro color en el uso de la memoria o una disminución del uso de memoria que se correlaciona con las implementaciones, una fuga de memoria podría ser la causa de los problemas de rendimiento. Una fuga de memoria también puede causar una recolección de elementos no utilizados frecuente, lo que genera una latencia más alta. Si no puedes rastrear este problema hasta un problema en el código, intenta aprovisionar instancias más grandes con más memoria.

Fuga de recursos

Si una instancia de tu aplicación muestra una latencia creciente que se correlaciona con la antigüedad de la instancia, es posible que tengas una filtración de recursos que cause problemas de rendimiento. La latencia disminuye después de que se completa una implementación. Por ejemplo, una estructura de datos que se vuelve más lenta con el tiempo debido al mayor uso de CPU puede hacer que cualquier carga de trabajo vinculada a la CPU se vuelva más lenta.

Optimización de código

Para reducir la latencia en App Engine, optimiza el código con los siguientes métodos:

  • Trabajo sin conexión: Usa Cloud Tasks para evitar que las solicitudes de los usuarios bloqueen la aplicación mientras espera que se complete una tarea, como el envío de correos electrónicos.

  • Llamadas a la API asíncronas: Asegúrate de que tu código no esté bloqueado a la espera de que se complete una llamada a la API.

  • Llamadas a la API por lotes: La versión por lotes de las llamadas a la API suele ser más rápida que enviar llamadas individuales.

  • Desnormalizar modelos de datos: Reduce la latencia de las llamadas hechas a la capa de persistencia de los datos mediante la desnormalización de tus modelos de datos.

Dependencias de la aplicación

Supervisa las dependencias de tu aplicación para detectar si los picos de latencia se correlacionan con una falla de la dependencia.

Un cambio en la carga de trabajo y un aumento en el tráfico pueden causar que aumente la latencia de una dependencia.

Dependencia sin escalamiento

Si la dependencia de tu aplicación no escala a medida que aumenta la cantidad de instancias de App Engine, la dependencia puede sobrecargarse cuando el tráfico aumenta. Un ejemplo de una dependencia que podría no escalar es una base de datos SQL. Una mayor cantidad de instancias de la aplicación genera una mayor cantidad de conexiones de bases de datos, lo que podría causar una falla en cascada, ya que no se inicia la base de datos. Para solucionar este problema, haz lo siguiente:

  1. Implementa una versión predeterminada nueva que no se conecte a la base de datos.
  2. Cerrar la versión predeterminada anterior.
  3. Implementa una versión no predeterminada nueva que se conecte a la base de datos.
  4. Migra el tráfico a la versión nueva.

Como medida preventiva, diseña tu aplicación para que descarte las solicitudes a la dependencia mediante la regulación adaptable.

Falla de la capa de almacenamiento en caché

Para acelerar las solicitudes, usa varias capas de almacenamiento en caché, como el almacenamiento en caché de borde, Memcache y la memoria de la instancia. Un error en una de estas capas de almacenamiento en caché puede provocar un aumento repentino de la latencia. Por ejemplo, una limpieza de Memcache puede hacer que más solicitudes vayan a un Datastore más lento.