Se produce una "tormenta de reintento" cuando los clientes están configurados para reintentar un número determinado de veces antes de darse por vencido, es necesaria una política de reintento debido a que se producirá la pérdida de paquetes en el funcionamiento normal de un servicio.
Toma este ejemplo:
Si, por ejemplo, los servicios en su conjunto se ampliaron para admitir 80,000 solicitudes por segundo y se ejecutan a aproximadamente el 80% de la capacidad, un aumento en el tráfico que hizo que el servicio recibiera 101,000 solicitudes por segundo provocaría que 1,000 de esas solicitudes fallaran.
Cuando entran en vigencia las políticas de reintento, terminas con más de 1,000 solicitudes adicionales, dependiendo de dónde se detectó la falla, lo que empujaría el servicio en su conjunto a 102,000 solicitudes por segundo; a partir de ahí, tu servicio entra en una espiral de muerte duplicando el número de solicitudes fallidas cada segundo.
Aparte del sobreaprovisionamiento masivo de servicios más allá de la transacción pico proyectada, lo que sería ineficiente. ¿Qué estrategias puede emplear para evitar "volver a intentar las tormentas"?
fuente
Respuestas:
Depende de lo que intentes evitar.
Si está tratando de evitar cualquier interrupción del servicio de algo que es un servicio realmente crítico (estoy pensando en términos de "las personas morirán si mi llamada API no se atiende de manera adecuada"), solo necesita presupuestar para las enormes ineficiencias que provienen de un suministro excesivo de recursos dedicados. Y sí, tienen que ser dedicados, nada de esto permite el aumento de picos de tráfico, por lo que el aumento de múltiples servicios provocaría una interrupción.
En el escenario mucho más probable de que su servicio no funcione, sería inconveniente que pueda abordar el problema tanto desde el lado del cliente como del servidor. Aunque vale la pena señalar que es lógicamente imposible resolver el problema de demasiado tráfico porque sin procesar el tráfico (que consume recursos) no puede saber si es un reintento, si es un reintento para una solicitud que fue exitosa pero se manejó incorrectamente por el cliente, si es un DDOS, etc. Pero puede mitigar el impacto.
En el código del cliente, escriba una lógica de reintento razonable que tenga un límite superior y un mecanismo para fallar con gracia. De esa manera, no se queda con sus usuarios en un ciclo infinito de solicitudes fallidas y simplemente les da un error diciéndoles que intenten lo que sea que hayan hecho en poco tiempo.
Para la infraestructura del lado del servidor , la solución más simple es acelerar. Límites estrictos a las solicitudes, especialmente si puede intentar distribuirlas lógicamente en función de su caso de uso específico (es decir, si tiene un servicio centralizado que toma algunas decisiones difíciles, ¿desea comenzar a bloquear las solicitudes geográficamente distantes que podrían dar lugar a hilos colgados? ¿lado del servidor? ¿O desea distribuir su interrupción inevitable pero menor de manera uniforme? etc) Básicamente se reduce al hecho de que devolver un 503 intencionalmente desde una puerta de enlace es muchísimo más barato que dejar pasar la solicitud y enviar un 504 de todas formas. Básicamente obligar a los clientes a comportarse en función de lo que puede proporcionar actualmente y proporcionar las respuestas correctas para que los clientes puedan reaccionar adecuadamente.
fuente
Una forma de prevenir estas tormentas de reintento es mediante el uso de mecanismos de retroceso.
Desde la sección Implementar backoff on retry de Google App Engine Designing for Scale :
La mayoría de las API de GAE ya tienen dichos mecanismos / políticas de retroceso habilitados de forma predeterminada.
fuente