He estado leyendo mucho sobre arquitecturas de microservicios para aplicaciones de servidor y me he preguntado cómo el uso de la red interna no es un cuello de botella o una desventaja significativa en comparación con una arquitectura monolítica.
En aras de la precisión, aquí están mis interpretaciones de los dos términos:
Arquitectura monolítica: una aplicación en un solo idioma que maneja todas las funciones, datos, etc. Un equilibrador de carga distribuye las solicitudes del usuario final a través de múltiples máquinas, cada una de las cuales ejecuta una instancia de nuestra aplicación.
Arquitectura de microservicios: muchas aplicaciones (microservicios) manejan una pequeña porción de la funcionalidad y los datos. Cada microservicio expone una API común a la que se accede a través de la red (a diferencia de la comunicación entre procesos o la memoria compartida en la misma máquina). Las llamadas a la API se agrupan principalmente en el servidor para producir una página, aunque tal vez parte del trabajo lo realiza el cliente consultando microservicios individuales.
Para mi ingenua imaginación, parece que una arquitectura de microservicios utiliza un tráfico de red lento en lugar de recursos más rápidos en la misma máquina (la memoria y el disco). ¿Cómo se asegura que las consultas API a través de la red interna no disminuyan el tiempo de respuesta general?
fuente
Respuestas:
Las redes internas a menudo usan conexiones de 1 Gbps, o más rápido. Las conexiones o enlaces de fibra óptica permiten anchos de banda mucho más altos entre los servidores. Ahora imagine el tamaño promedio de una respuesta JSON de una API. ¿Cuántas de esas respuestas se pueden transmitir a través de una conexión de 1 Gbps en un segundo?
Realmente hagamos los cálculos. 1 Gbps es 131 072 KB por segundo. Si una respuesta JSON promedio es de 5 KB (¡lo cual es bastante!), Puede enviar 26 214 respuestas por segundo a través del cable con solo un par de máquinas . No está tan mal, ¿no?
Es por eso que la conexión de red no suele ser el cuello de botella.
Otro aspecto de los microservicios es que puede escalar fácilmente. Imagine dos servidores, uno que aloja la API y otro que la consume. Si alguna vez la conexión se convierte en el cuello de botella, simplemente agregue otros dos servidores y podrá duplicar el rendimiento.
Esto es cuando nuestras 26 214 respuestas por segundo anteriores se vuelven demasiado pequeñas para la escala de la aplicación. Agrega otros nueve pares y ahora puede atender 262 140 respuestas.
Pero volvamos a nuestro par de servidores y hagamos algunas comparaciones.
Si una consulta promedio no almacenada en caché a una base de datos tarda 10 ms., Está limitado a 100 consultas por segundo. 100 consultas. 26 214 respuestas. Lograr la velocidad de 26 214 respuestas por segundo requiere una gran cantidad de almacenamiento en caché y optimización (si la respuesta realmente necesita hacer algo útil, como consultar una base de datos; las respuestas de estilo "Hola Mundo" no califican).
En mi computadora, en este momento, DOMContentLoaded para la página de inicio de Google sucedió 394 ms. después de que se envió la solicitud. Eso es menos de 3 solicitudes por segundo. Para la página de inicio de Programmers.SE, sucedió 603 ms. después de que se envió la solicitud. Eso no es ni siquiera 2 solicitudes por segundo. Por cierto, tengo una conexión a Internet de 100 Mbps y una computadora rápida: muchos usuarios esperarán más.
Si el cuello de botella es la velocidad de la red entre los servidores, esos dos sitios podrían literalmente hacer miles de llamadas a diferentes API mientras sirven la página.
Esos dos casos muestran que la red probablemente no será su cuello de botella en teoría (en la práctica, debe hacer los puntos de referencia y los perfiles reales para determinar la ubicación exacta del cuello de botella de su sistema particular alojado en un hardware en particular). El tiempo dedicado a hacer el trabajo real (serían consultas SQL, compresión, lo que sea) y enviar el resultado al usuario final es mucho más importante.
Piensa en bases de datos
Por lo general, las bases de datos se alojan por separado de la aplicación web que las usa. Esto puede plantear una preocupación: ¿qué pasa con la velocidad de conexión entre el servidor que aloja la aplicación y el servidor que aloja la base de datos?
Parece que hay casos en los que, de hecho, la velocidad de conexión se vuelve problemática, es decir, cuando almacena grandes cantidades de datos que no necesitan ser procesados por la base de datos y que deberían estar disponibles en este momento (es decir, archivos binarios grandes). Pero tales situaciones son raras: en la mayoría de los casos, la velocidad de transferencia no es tan grande en comparación con la velocidad de procesamiento de la consulta en sí.
Cuando la velocidad de transferencia realmente importa es cuando una empresa aloja grandes conjuntos de datos en un NAS, y varios clientes acceden al NAS al mismo tiempo. Aquí es donde una SAN puede ser una solución. Dicho esto, esta no es la única solución. Los cables Cat 6 pueden soportar velocidades de hasta 10 Gbps; La unión también se puede utilizar para aumentar la velocidad sin cambiar los cables o adaptadores de red. Existen otras soluciones, que implican la replicación de datos en múltiples NAS.
Olvídate de la velocidad; pensar en la escalabilidad
Un punto importante de una aplicación web es poder escalar. Si bien el rendimiento real es importante (porque nadie quiere pagar por servidores más potentes), la escalabilidad es mucho más importante, ya que le permite lanzar hardware adicional cuando sea necesario.
Si tiene una aplicación no particularmente rápida, perderá dinero porque necesitará servidores más potentes.
Si tiene una aplicación rápida que no puede escalar, perderá clientes porque no podrá responder a una demanda creciente.
Del mismo modo, las máquinas virtuales fueron percibidas hace una década como un gran problema de rendimiento. De hecho, alojar una aplicación en un servidor frente a alojarla en una máquina virtual tuvo un importante impacto en el rendimiento. Si bien la brecha es mucho más pequeña hoy, todavía existe.
A pesar de esta pérdida de rendimiento, los entornos virtuales se hicieron muy populares debido a la flexibilidad que brindan.
Al igual que con la velocidad de la red, puede encontrar que VM es el cuello de botella real y dada su escala real, ahorrará miles de millones de dólares al alojar su aplicación directamente, sin las VM. Pero esto no es lo que sucede para el 99.9% de las aplicaciones: su cuello de botella está en otro lugar, y el inconveniente de una pérdida de unos pocos microsegundos debido a la VM se compensa fácilmente con los beneficios de la abstracción y escalabilidad del hardware.
fuente
Creo que estás leyendo demasiado en la parte 'micro'. No significa reemplazar cada clase con un servicio de red, sino crear componentes de una aplicación monolítica en componentes de tamaño razonable, cada uno de los cuales se ocupa de un aspecto de su programa. Los servicios no se comunican entre sí, por lo que en el peor de los casos, ha dividido una solicitud de red grande en varias más pequeñas. De todos modos, los datos devueltos no serán significativamente diferentes de los que recibe (aunque podría devolver más datos y consolidarlos en el cliente)
fuente
Al estructurar su código y acceso a los recursos de manera que el sistema resultante pueda ser lo suficientemente flexible como para ejecutarse como una aplicación monolítica o distribuida a través de la configuración. Si abstrae el mecanismo de comunicación detrás de alguna interfaz común y construye su sistema con concurrencia en mente, puede optimizar fácilmente todo después de haber perfilado su sistema y encontrado los cuellos de botella reales.
fuente
Me gustaría agregar una perspectiva diferente, desde una industria diferente con supuestos muy diferentes: simulación distribuida (a nivel de entidad). Conceptualmente, esto se parece mucho a un videojuego FPS distribuido. Diferencias clave: todos los jugadores comparten algún estado: dónde está el dragón en este momento; sin llamadas a la base de datos; todo se mantiene en la RAM para velocidad y baja latencia, el rendimiento es menos relevante (pero supongo que tampoco se puede ignorar por completo).
Puede pensar en cada aplicación participante como un monolito (que representa todas las facetas de un jugador) o como un microservicio (que representa solo un jugador en una multitud).
Mis colegas han mostrado interés en desglosar una sola aplicación participante, más allá en microservicios más pequeños que podrían compartirse, por ejemplo, arbitraje de daños o cálculos de línea de visión, cosas que generalmente se agrupan en las simulaciones.
El problema es la latencia de despachar llamadas y esperar solicitudes. El ancho de banda es irrelevante y abundante de todos modos, como han señalado otros. Pero si un cálculo de la línea de visión pasa de 1 microsec a 100 microsec (por ejemplo, debido a la cola en el nuevo microservicio compartido entre todas las aplicaciones del reproductor), es una pérdida enorme (podría necesitar varios o muchos cálculos de línea de visión para cada actualización, varias actualizaciones / segundo).
Piense detenidamente sobre cómo funcionan los servicios, cuándo se llaman y qué datos se intercambian. Nuestras aplicaciones ya no intercambian solo información de posición, intercambian información de cálculo muerto: estoy en la posición x, en dirección y a la velocidad q. Y no tengo que actualizar mi información hasta que esos supuestos cambien. Muchas menos actualizaciones, y la latencia (aunque sigue siendo un problema) aparece proporcionalmente con menos frecuencia.
Entonces, en lugar de solicitar un servicio de grano fino a una frecuencia más alta, intente reducir la frecuencia de la siguiente manera:
Ahora recuerde verificar sus suposiciones sobre su sistema. Si está más preocupado por el rendimiento que por la latencia, o no ha tenido un estado compartido, etc., entonces, por todos los medios, use microservicios donde tengan sentido. Solo digo que tal vez no los uses donde no tengan sentido.
fuente
Tu ingenua imaginación es correcta. Y a menudo eso no importa. Las máquinas modernas son rápidas. Las principales ventajas de la arquitectura de micro servicios se ven en el esfuerzo y el tiempo de desarrollo y mantenimiento.
Y, por supuesto, no hay una regla que diga que no puede usar la memoria compartida o incluso desplegar físicamente múltiples servicios en un ejecutable. Siempre y cuando lo diseñes no dependas de eso.
fuente
Como mucha gente mencionó, no se trata de cuellos de botella en la red. Se trata más de la fragilidad de la red. Entonces, el primer paso es evitar la comunicación sincrónica. Es más fácil de lo que parece. Todo lo que necesita son servicios con límites correctos. Los límites correctos dan como resultado que los servicios sean autónomos, débilmente acoplados y altamente cohesivos. Un buen servicio no necesita información de otro servicio, ya la tiene. La única forma en que los buenos servicios se comunican es a través de eventos. Los buenos servicios son eventualmente consistentes también, por lo que no hay transacciones distribuidas.
La forma de lograr esta bondad es identificar primero las capacidades de su negocio. La capacidad empresarial es una responsabilidad empresarial específica. Alguna contribución al valor comercial general. Así que aquí está mi secuencia de pasos que tomo cuando pienso en los límites del sistema:
Tenga en cuenta que el servicio comercial incluye personas, aplicaciones, procesos comerciales. Por lo general, solo una parte está representada como autoridad técnica.
Esto podría sonar un poco abstracto, por lo que probablemente un ejemplo de identificación de límites de servicio sería de algún interés.
fuente
Solo otro factor para agregar a las respuestas actuales. Con un servicio de grano grueso . Desea evitar la latencia de todas las llamadas, por lo que en lugar de hacer 10 llamadas, realice una llamada que obtenga 10 datos necesarios en un DTO.
Y recuerde que los microservicios no son tan micro como la gente piensa.
fuente