[Diseño de arquitectura de microservicios] Los microservicios no son mágicos: tiempo de espera de procesamiento

Los microservicios son importantes. Pueden conducir a grandes ganancias para nuestra arquitectura y equipos, pero los microservicios también tienen un gran costo. A medida que los microservicios, sin servidor y otras arquitecturas de sistemas distribuidos se vuelven más frecuentes en la industria, es fundamental que internalicemos sus problemas y estrategias para resolverlos. En este artículo, examinaremos un ejemplo de los muchos problemas espinosos que pueden presentar los límites de la red: los tiempos de espera.

Antes de que le dé pavor el término "sistema distribuido", recuerde que incluso una pequeña aplicación React con un backend Node, o un simple cliente de iOS que se comunique con AWS Lambda, representa un sistema distribuido. Mientras lee esta publicación de blog, ya está participando en un sistema distribuido que incluye su navegador web, red de entrega de contenido y sistema de almacenamiento de archivos.

En términos de antecedentes, supondré que comprende cómo realizar llamadas a la API en el idioma de su elección y manejar su éxito y fracaso, pero ya sea que esas llamadas a la API sean síncronas o asíncronas, HTTP o no. Si te encuentras con términos o ideas que no te son familiares, ¡no te preocupes! Estoy feliz de tener más debates en Twitter o en otros lugares, y he tratado de agregar enlaces donde corresponda.

El problema que vamos a explorar es este: si tenemos una llamada a la API muy, muy lenta que finalmente se agota y suponemos que (a) tiene éxito o (b) falla, tenemos un error. Los tiempos de espera (o peor, las esperas infinitamente largas) son un hecho fundamental de los sistemas distribuidos, y debemos saber cómo manejarlos.

pregunta


Comencemos con un experimento mental: ¿alguna vez le envió un correo electrónico a un compañero de trabajo para pedirle algo?

  • [Martes, 9:58 a. m.] Tú: "Oye, ¿puedes agregarme a la lista de mentores potenciales de nuestra empresa?"

  • colega:"……"

  • [Viernes, 2:30 p. m.] Tú: [?]

¿Qué deberías hacer?

Si desea que su solicitud se cumpla, eventualmente deberá asegurarse de que no haya respuesta. ¿Esperarás más? ¿Cuánto tiempo quieres esperar?

Entonces, una vez que haya decidido cuánto tiempo esperar, ¿qué acción tomará? ¿Intentaste enviar el correo electrónico de nuevo? ¿Probaste diferentes medios de comunicación? ¿Crees que no harán eso?

OK, ¿ahora qué diablos está pasando aquí? Nos gustaría ver este comportamiento de solicitud-respuesta:

05299aecbcbd799a98f6b626054ad491.png

Pero algo salió mal. Hay varias posibilidades:

  • Nunca entendieron el mensaje.

9e39a000a5bd4be590e7a13d61bc937c.png

  • Recibieron el correo, lo procesaron con éxito y le enviaron una respuesta que nunca supieron de usted (o fue a su carpeta de correo no deseado).

fa52b63d6632b1ff09c90f0e9d5429a1.png

  • Obtuvieron la información, pero todavía están pensando en ella, o la pierden, o [¡jadeo! ] Se olvidaron.

396f44aba9b73bedaa30f2ea70254853.png

  • En última instancia, ¡simplemente no lo sabemos!

44ea42fdc2caea02bb31f790c9a9281b.png

Este es el problema que surge con cualquier comunicación en un sistema distribuido.

Podemos retrasar nuestras solicitudes, procesamiento o respuestas, y estos retrasos pueden ser arbitrariamente largos. Entonces, al igual que con el ejemplo del correo electrónico, debemos asegurarnos de que haya una respuesta a la pregunta "¿cuánto tiempo tenemos que esperar?" , y llamamos tiempo de espera a esa duración.

Si solo toma una lección de este artículo, que así sea: use tiempos de espera . De lo contrario, corre el riesgo de esperar eternamente una operación que nunca se completará.

Pero, ¿qué hacemos una vez que alcanzamos el tiempo de espera, el límite superior de espera?

método


Hay varias formas comunes en que las personas encuentran tiempos de espera en las llamadas al sistema remoto. No pretendo que esta lista sea exhaustiva, pero cubre muchos de los escenarios más comunes que he visto.

Método 1


Cuando obtenga un tiempo de espera, asuma que tuvo éxito y continúe.

Por favor, no hagas esto. [1] Desafortunadamente, debo decir que esta es una elección involuntaria común, incluso en aplicaciones de producción, con algunas consecuencias de UX bastante malas. Si asumimos que la cirugía fue un éxito, nosotros, los consumidores pobres, asumiremos razonablemente que las cosas salieron bien, solo para decepcionarnos y confundirnos más tarde cuando descubramos los resultados.

Cada vez que tenga una llamada de networking, busque éxitos y fracasos. Por ejemplo, si está utilizando una API asíncrona en JavaScript a través de Promise.then(...), pregúntese dónde está el .catch(...) correspondiente. Si falta, es casi seguro que tiene un error.

En algunos casos muy especiales, es posible que no le importe si la solicitud tiene éxito o falla. UDP es un protocolo muy exitoso con esta propiedad. Además, una gran cantidad de software está dañado, ¡sigue ganando dinero! Pero no deje que este sea su valor predeterminado: primero agote sus otras opciones.

Método #2


Para solicitudes de lectura, use caché o predeterminado.

Esta podría ser una buena opción si su solicitud es una solicitud de lectura y no pretende tener ningún impacto en el lado remoto. En este caso, puede usar valores almacenados en caché de solicitudes exitosas anteriores. Alternativamente, puede usar el valor predeterminado si aún no hay solicitudes exitosas o el almacenamiento en caché no tiene sentido en su caso. Este enfoque es relativamente simple: no agrega mucha sobrecarga de rendimiento ni complejidad de implementación. Pero tenga en cuenta que si está utilizando un caché fuera de proceso al que se accede a través de la red (por ejemplo, memcached, Redis, etc.), entonces volverá a algo así, donde sus solicitudes pueden agotar el tiempo de espera del caché. mismo _

Método #3

Cuando encuentre un tiempo de espera, suponga que la operación remota falló y vuelva a intentarlo automáticamente.

Esto plantea más preguntas:

  • ¿Qué sucede si no es seguro volver a intentarlo ? ¿Es simplemente molesto que el servicio en el otro extremo de la conexión de red se duplique? ¿O estás cargando dos veces tu tarjeta de crédito? (!)

  • ¿ Debería volver a intentarlo de forma síncrona o asíncrona ?

  • Si vuelve a intentarlo sincrónicamente, esos reintentos lo retrasarán desde el punto de vista del consumidor . ¿Existe alguna posibilidad de que no esté cumpliendo con sus expectativas? Esto es especialmente importante en los servicios, más que en las aplicaciones de usuario final.

  • Si vuelve a intentarlo de forma asíncrona, ¿qué les está diciendo a sus consumidores sobre el éxito de la operación ? ¿Los prueba uno a la vez o vuelve a intentarlo en lotes durante un período de tiempo?

  • ¿ Cuántas veces debe volver a intentarlo ? (¿Una vez? ¿Dos veces? ¿10 veces? ¿Hasta el éxito?)

  • ¿ Cómo debe demorar entre reintentos ? (Retroceso exponencial [p. ej., 1, 2, 4, 8, 16, ...] ¿limitado por la latencia máxima? ¿Usando interpolación?)

  • Si los servidores remotos tienen problemas de rendimiento debido a la sobrecarga , ¿los empeorarán los reintentos?

Si la API remota puede volver a intentarlo de forma segura, lo llamamos idempotente. Sin la propiedad idempotente, podría crear datos duplicados (como en el caso de los cargos de la tarjeta de crédito) o provocar una condición de carrera (es decir, si intenta cambiar su dirección de correo electrónico dos veces y el primero vuelve a intentarlo después de que se complete el segundo).

Hacer que los reintentos automáticos sean seguros puede requerir un esfuerzo arquitectónico significativo en muchos casos. Sin embargo, si puede volver a intentarlo de forma segura (por ejemplo, mediante el envío de UUID de solicitud y hacer que el lado remoto realice un seguimiento de estos), las cosas se vuelven muy, muy simples. Consulte la API de Stripe para ver un buen ejemplo de esto en acción.

Método #4


Compruebe si la solicitud se ha realizado correctamente e inténtelo de nuevo si es seguro.

La idea aquí es que, en algunos casos, podemos hacer un seguimiento con otra solicitud después de una solicitud con tiempo de espera agotado, preguntándonos sobre el estado de la solicitud original. Este enfoque obviamente requiere la existencia de un punto final que pueda darnos la información que queremos. Dado tal punto final, si el punto final dice que nuestra solicitud fue exitosa, podemos decir explícitamente que no necesitamos volver a intentarlo.

Pero hay un problema grave aquí, no podemos saber realmente si es seguro volver a intentarlo. Debido a que, por lo general, nuestro servicio remoto puede recibir la solicitud pero aún la está procesando, el extremo de la consulta que estamos verificando no podrá confirmar el éxito . Por supuesto, ¡la verificación en sí puede expirar! Es posible que el servidor remoto sea completamente inaccesible por las mismas razones que la falla inicial, pero incluso si eso es cierto, todavía no tenemos forma de saber si el problema ocurrió antes o después de que se procesara la solicitud inicial.

Método #5


Renunciar y dejar que el usuario lo averigüe.

Esto requiere la menor cantidad de esfuerzo y podría decirse que evita que tomemos malas decisiones, por lo que en muchos casos esta puede ser la mejor opción. También debemos preguntarnos: ¿ Pueden nuestros usuarios averiguar qué hacer correctamente? ¿Tienen suficiente información y conocimientos sobre otros sistemas para determinar cómo avanzar ?

En algunos casos, puede ser mejor informar a nuestros consumidores sobre el problema. Para cualquier método que involucre reintentos, aún podemos terminar volviendo a este camino si no queremos permitir un número infinito de reintentos.

en conclusión


Entonces, en este punto, las cosas pueden parecer sombrías. Los sistemas distribuidos son difíciles y parece que no podemos elegir una de estas soluciones como una panacea. Si te sientes fracasado, anímate y no permitas que lo perfecto sea enemigo de lo bueno.

Usar tiempo de espera.


Cada solicitud de red debe tener algún tiempo de espera, incluso si el tiempo de espera es largo, como 5 segundos, 10 segundos o [¡gulp!] Incluso más. Elegir un tiempo de espera puede ser complicado: no desea tener demasiados errores (falsos positivos) cuando las solicitudes finalmente tienen éxito, y no desea perder demasiado tiempo y arriesgarse a una aplicación en mal estado. Puede determinar un buen valor observando la distribución y las tendencias de las solicitudes históricas y las propias garantías de rendimiento o el perfil de riesgo de su aplicación.

Bajo ninguna circunstancia queremos que la cola de nuestro servidor de aplicaciones, el grupo de conexiones, el búfer de anillo o cualquier cuello de botella se obstruya con algo que esperará para siempre. Definitivamente, puede investigar y agregar cosas más sofisticadas, como disyuntores y mamparos, según sus necesidades de producción, pero los tiempos de espera son económicos y están bien respaldados por las bibliotecas. ¡usalos, usalos a ellos!

Haga que el reintento sea seguro de forma predeterminada.


Es interesante que hables de "idempotencia" además de hacer tu código más simple y seguro.

Considere delegar el trabajo de manera diferente.


La mensajería asíncrona tiene aquí algunas propiedades atractivas, porque su servicio remoto ya no necesita ser rápido y estar disponible; solo su intermediario de mensajes puede hacerlo. Sin embargo, la mensajería/la asincronía no es una panacea; aún debe asegurarse de que el intermediario reciba el mensaje . Desafortunadamente, ¡esto puede ser difícil! Los intermediarios de mensajes también tienen ventajas y desventajas. Sus usuarios tendrán una idea de cuándo necesitan volver a intentarlo. Por ejemplo, si hay un retraso en el procesamiento del mensaje, pueden decidir volver a enviarlo porque su pedido aún no aparece en el historial de pedidos. Pueden surgir problemas similares con las plataformas distribuidas de registro/transmisión. Si está considerando la ruta de mensajería (¡incluso si no lo está, en realidad!), eche un vistazo de cerca a los patrones de integración empresarial: a pesar de su antigüedad, los patrones que contiene son extremadamente relevantes para las arquitecturas actuales.

Y a riesgo de ser una caca de fiesta, ¡no olvide que puede mover o eliminar ese perímetro de red por completo! No hay vergüenza en convertir un problema difícil en uno fácil. Entonces, tal vez pueda usar una solicitud de red en lugar de cinco, o puede alinear dos servicios juntos. O tal vez tome uno de los enfoques anteriores para manejar los tiempos de espera de una manera confiable y segura. Cualquiera que sea la forma que elija, recuerde que a sus usuarios no les importa si usa microservicios, solo quieren que las cosas funcionen.

Este artículo: https://architect.pub/microservices-arent-magic-handling-timeouts
Discusión: Knowledge Planet [Chief Architect Circle] o agregue la trompeta de WeChat [ca_cto] o agregue el grupo QQ [792862318]
sin publico
 
【jiagoushipro】
【Super Arquitecto】
Brillante explicación gráfica y detallada de la metodología de la arquitectura, la práctica de la arquitectura, los principios técnicos y las tendencias técnicas.
Te estamos esperando, por favor escanea y presta atención.
Trompeta WeChat
 
[ca_cea]
Comunidad de 50,000 personas, discutiendo: arquitectura empresarial, computación en la nube, big data, ciencia de datos, Internet de las cosas, inteligencia artificial, seguridad, desarrollo completo, DevOps, digitalización.
 

grupo QQ
 
[285069459] Intercambio en profundidad de arquitectura empresarial, arquitectura empresarial, arquitectura de aplicaciones, arquitectura de datos, arquitectura técnica, arquitectura de integración, arquitectura de seguridad. Y diversas tecnologías emergentes como big data, cloud computing, Internet de las Cosas, inteligencia artificial, etc.
Únase al grupo QQ para compartir valiosos informes y productos secos.

numero de video [Super arquitecto]
Comprenda rápidamente los conceptos, modelos, métodos y experiencias básicos relacionados con la arquitectura en 1 minuto.
1 minuto al día, la estructura es familiar.

planeta del conocimiento [Círculo de arquitectos en jefe] Pregunte a los grandes nombres, póngase en contacto con ellos o comparta información privada.  

Himalaya [Super arquitecto] Aprenda sobre la última experiencia de arquitectura e información de tecnología negra en la carretera o en el automóvil. [Momentos inteligentes, el Sr. Arquitectura les hablará de tecnología negra]
planeta del conocimiento Conoce más amigos, lugar de trabajo y chat técnico. Knowledge Planet【Lugar de trabajo y tecnología】
LinkedIn Harry https://www.linkedin.com/in/architect-harry/
grupo de LinkedIn Grupo de arquitectura de LinkedIn https://www.linkedin.com/groups/14209750/
Weibo‍‍ 【Súper Arquitecto】 momento inteligente‍
bilibili 【Súper Arquitecto】

Tik Tok 【cea_cio】Super Arquitecto

trabajador rapido 【cea_cio_cto】Super Arquitecto

pequeño libro rojo [cea_csa_cto] Súper Arquitecto  

sitio web CIO (director de información) https://cio.ceo
sitio web CIO, CTO y CDO https://cioctocdo.com
sitio web Arquitecto práctica compartida https://arquitecto.pub   
sitio web Compartir el desarrollo de la nube del programador https://pgmr.cloud
sitio web Comunidad de arquitectos jefe https://jiagoushi.pro
sitio web Plataforma de desarrollo y desarrollo de aplicaciones. https://apaas.dev
sitio web Red de información sobre el desarrollo https://xinxi.dev
sitio web súper arquitecto https://jiagou.dev
sitio web Formación técnica empresarial https://peixun.dev
sitio web Libro del programador https://pgmr.pub    
sitio web chat de desarrollador https://blog.developer.chat
sitio web Colección CPO https://cpo.trabajo

Gracias por su atención, reenvío, me gusta y ver.

Supongo que te gusta

Origin blog.csdn.net/jiagoushipro/article/details/131950667
Recomendado
Clasificación