Diagnóstico y solución de problemas de tiempo de espera de la solicitud del SDK de .NET en Azure Cosmos DB
SE APLICA A: NoSQL
El error HTTP 408 se produce si el SDK no puede completar la solicitud antes de que se agote el límite de tiempo de espera.
Es importante asegurarse de que el diseño de la aplicación siga nuestra guía para diseñar aplicaciones resistentes con SDK de Azure Cosmos DB para asegurarse de que reacciona correctamente a diferentes condiciones de red. La aplicación debe tener reintentos en su lugar para los errores de tiempo de espera, ya que normalmente se esperan en un sistema distribuido.
Al evaluar el caso en caso de error por tiempo de espera:
- ¿Qué impacto tiene el problema, si se mide comparando el volumen de operaciones afectadas con el de operaciones que sí se realizaron correctamente? ¿Es este valor aplicable a los Acuerdos de Nivel de Servicio?
- ¿Se ve afectada la latencia o disponibilidad de P99?
- ¿Afectan los errores a todas las instancias de la aplicación, o solo a un subconjunto? Si el problema se reduce a un subconjunto de instancias, normalmente se trata de un problema relacionado con ellas.
Personalización del tiempo de espera en el SDK de.NET para Azure Cosmos DB
El SDK tiene dos alternativas distintas a los tiempos de espera de control, cada una con un ámbito diferente.
Tiempos de espera de nivel de solicitud
La configuración CosmosClientOptions.RequestTimeout
(o ConnectionPolicy.RequestTimeout
para SDK v2) permite establecer un tiempo de espera para la solicitud de red después de que la solicitud deje el SDK y esté en la red, hasta que se reciba una respuesta.
La configuración CosmosClientOptions.OpenTcpConnectionTimeout
(o ConnectionPolicy.OpenTcpConnectionTimeout
para SDK v2) permite establecer un tiempo de espera para el tiempo dedicado a abrir una conexión inicial. Una vez abierta una conexión, las solicitudes posteriores usarán la conexión.
Una operación iniciada por un usuario puede abarcar varias solicitudes de red, como por ejemplo, reintentos. Estas dos configuraciones son por solicitud, no de un extremo a otro de una operación.
CancellationToken
Todas las operaciones asincrónicas del SDK tienen un parámetro CancellationToken opcional. Este parámetro CancellationToken se utiliza en toda la operación y en todas las solicitudes de red y reintentos. Entre las solicitudes de red, se puede comprobar el parámetro de cancelación. Una operación se cancela si el token relacionado ha expirado. El token de cancelación se debe usar para definir un tiempo de espera esperado aproximado en el ámbito de la operación.
Nota:
El parámetro CancellationToken
es un mecanismo que permite a la biblioteca comprobar la cancelación cuando no cause un estado no válido. Es posible que la operación no se cancele exactamente cuando el tiempo definido en la cancelación esté activo. En su lugar, una vez que se agote el tiempo, se cancelará cuando sea seguro.
Pasos para solucionar problemas
La lista siguiente contiene las causas y las soluciones conocidas para las excepciones de tiempo de espera de solicitud.
CosmosOperationCanceledException
Este tipo de excepción es común cuando la aplicación pasa CancellationTokens a las operaciones del SDK. El SDK comprueba el estado de CancellationToken
entre reintentos y, si CancellationToken
se cancela, anulará la operación actual con esta excepción.
La excepción Message
/ ToString()
también indicará el estado de CancellationToken
a través de Cancellation Token has expired: true
y contendrá diagnósticos con el contexto de la cancelación de las solicitudes implicadas.
Estas excepciones son seguras para reintentarlo y se pueden tratar como tiempos de espera desde la perspectiva del reintento.
Solución
Compruebe la hora configurada en CancellationToken
, asegúrese de que es mayor que RequestTimeout y CosmosClientOptions.OpenTcpConnectionTimeout (si usa el modo directo).
Si el tiempo disponible en CancellationToken
es menor que los tiempos de espera configurados y el SDK tiene problemas de conectividad transitorios, el SDK no podrá reintentarlo y generará CosmosOperationCanceledException
.
Uso elevado de CPU
El uso elevado de la CPU es el caso más común. Para lograr una latencia óptima, el uso de la CPU debe ser de aproximadamente el 40 por ciento. Use 10 segundos como intervalo para supervisar el uso máximo de la CPU (no el promedio). Los picos de CPU son más habituales con consultas entre particiones en las que se pueden realizar varias conexiones para una sola consulta.
Los tiempos de espera contienen Diagnósticos, que incluyen:
"systemHistory": [
{
"dateUtc": "2021-11-17T23:38:28.3115496Z",
"cpu": 16.731,
"memory": 9024120.000,
"threadInfo": {
"isThreadStarving": "False",
....
}
},
{
"dateUtc": "2021-11-17T23:38:28.3115496Z",
"cpu": 16.731,
"memory": 9024120.000,
"threadInfo": {
"isThreadStarving": "False",
....
}
},
...
]
- Si los valores
cpu
superan el 70 %, es probable que el tiempo de estera se deba al agotamiento de la CPU. En este caso, la solución es investigar el origen del uso intensivo de la CPU y reducirlo, o bien escalar el equipo a un tamaño de recurso mayor. - Si los nodos
threadInfo/isThreadStarving
tienen valoresTrue
, la causa es el colapso de subprocesos. En este caso, la solución es investigar el origen u orígenes del colapso de subprocesos (subprocesos potencialmente bloqueados) o escalar los equipos a un tamaño de recurso mayor. - Si el tiempo
dateUtc
entre las medidas no es de aproximadamente 10 segundos, también indicaría que hay contención en el grupo de subprocesos. La CPU se mide como una tarea independiente que se pone en la cola en el grupo de subprocesos cada 10 segundos, si el tiempo entre las medidas es mayor, indicaría que las tareas asincrónicas no se pueden procesar de manera oportuna. Los escenarios más comunes son al bloquear llamadas a través de código asincrónico en el código de aplicación.
Solución
La aplicación cliente que usa el SDK se debe escalar vertical u horizontalmente.
La disponibilidad de puertos o de sockets puede ser reducida
Cuando se ejecutan en Azure, los clientes que usan el SDK de .NET pueden alcanzar el agotamiento de puertos SNAT (PAT) de Azure.
Solución 1
Si utiliza máquinas virtuales de Azure, siga la guía de agotamiento de los puertos SNAT.
Solución 2
Si utiliza Azure App Service, siga la guía de solución de problemas de errores de conexión y use el diagnóstico de App Service.
Solución 3
Si usa Azure Functions, compruebe que está siguiendo la recomendación para Azure Functions del mantenimiento de los clientes Singleton o estáticos para todos los servicios implicados (incluido Azure Cosmos DB). Compruebe los límites de servicio según el tipo y el tamaño del hospedaje de la aplicación de funciones.
Solución 4
Si usa un Proxy HTTP, asegúrese de que pueda admitir el número de conexiones configuradas en el SDK de ConnectionPolicy
. En caso contrario, se encontrará con problemas de conexión.
Creación de varias instancias de cliente
La creación de varias instancias de cliente podría provocar problemas de tiempo de espera y la contención de la conexión. El diagnóstico contiene dos propiedades importantes:
{
"NumberOfClientsCreated":X,
"NumberOfActiveClients":Y,
}
NumberOfClientsCreated
realiza un seguimiento del número de veces que se creó una instancia de CosmosClient
en el mismo AppDomain y NumberOfActiveClients
realiza un seguimiento de los clientes activos (no eliminados). La expectativa es que si se sigue el patrón singleton, X
coincidiría con el número de cuentas con las que funciona la aplicación y que X
es igual a Y
.
Si X
es mayor que Y
, significa que la aplicación está creando y eliminando instancias de cliente. Esto puede provocar contención de la conexión o contención de CPU.
Solución
Siga los consejos de rendimiento y use una sola instancia de CosmosClient por cuenta en un proceso completo. Evite crear y eliminar clientes.
Clave de partición activa
Azure Cosmos DB distribuye el rendimiento general aprovisionado de forma uniforme entre las particiones físicas. Cuando hay una partición activa, una o varias claves de partición lógica en una partición física están consumiendo todas las unidades de solicitud de la partición física por segundo (RU/s). Al mismo tiempo, las RU/s de otras particiones físicas no se usan. Como síntoma, el total de RU/s consumido será inferior al total de RU/s aprovisionadas en la base de datos o el contenedor, pero seguirá viendo la limitación (429s) en las solicitudes de la clave de la partición lógica activa. Use la métrica de consumo normalizado de RU para ver si la carga de trabajo está detectando una partición activa.
Solución
Elija una buena clave de partición que distribuya uniformemente el volumen y el almacenamiento de solicitudes. Obtenga más información acerca de cómo cambiar la clave de partición.
Alto grado de simultaneidad
La aplicación tiene un alto nivel de simultaneidad, lo que puede provocar contención en el canal.
Solución
La aplicación cliente que usa el SDK se debe escalar vertical u horizontalmente.
Solicitudes o respuestas de gran tamaño
Un gran número de solicitudes o respuestas puede provocar un bloqueo de encabezado de línea en el canal y agravar la contención, incluso con un nivel relativamente bajo de simultaneidad.
Solución
La aplicación cliente que usa el SDK se debe escalar vertical u horizontalmente.
La tasa de errores está dentro del Acuerdo de Nivel de Servicio de Azure Cosmos DB
La aplicación debe ser capaz de controlar los errores transitorios y volver a intentarlo cuando sea necesario. Las excepciones 408 no se reintentan porque, en las rutas de acceso de creación, no es posible saber si el servicio creó el elemento. Si se vuelve a enviar el mismo elemento para crearlo, se producirá una excepción de conflicto. La lógica de negocios de las aplicaciones de usuario podría personalizarse para administrar los conflictos, lo que produciría errores por la ambigüedad de un elemento existente frente al conflicto de un reintento de creación.
La tasa de errores infringe el Acuerdo de Nivel de Servicio de Azure Cosmos DB
Póngase en contacto con el soporte técnico de Azure.
Pasos siguientes
- Diagnóstico y solución de problemas al utilizar el SDK de Azure Cosmos DB para .NET.
- Más información sobre las directrices de rendimiento de .NET v3 y .NET v2.