Elementos básicos de aplicaciones distribuidas. Aproximación cero

Elementos básicos de aplicaciones distribuidas. Aproximación cero

El mundo no se detiene. El progreso crea nuevos desafíos tecnológicos. De acuerdo con los requisitos cambiantes, la arquitectura de los sistemas de información también debe evolucionar. Hoy hablaremos sobre la arquitectura orientada a eventos, la concurrencia, la paralelización, la asincronía y cómo se puede convivir pacíficamente con todo esto en Erlang.

Introducción

Dependiendo del tamaño del sistema que se está diseñando y sus requisitos, nosotros, los desarrolladores, elegimos el método de intercambio de información en el sistema. En la mayoría de los casos, para organizar la interacción de los servicios, una opción adecuada puede ser un esquema con un corredor, por ejemplo, basado en RabbitMQ o Kafka. Pero a veces el flujo de eventos, los SLA y el nivel de control sobre el sistema son tales que una solución de mensajería lista no es adecuada. Por supuesto, se puede complicar un poco el sistema, asumiendo la responsabilidad por el nivel de transporte y la formación de clústeres, utilizando, por ejemplo, ZeroMQ o nanomsg. Pero si el sistema tiene suficiente capacidad de procesamiento y las capacidades del clúster estándar de Erlang son adecuadas, la cuestión de incorporar una entidad adicional requiere un estudio detallado y una justificación económica.

El tema de las aplicaciones distribuidas reactivas es bastante amplio. Para ajustarnos al formato del artículo, el objeto de discusión de hoy serán solo entornos homogéneos basados en Erlang/Elixir. El ecosistema Erlang/OTP permite implementar una arquitectura reactiva con el menor esfuerzo posible. Sin embargo, en cualquier caso, necesitaremos una capa de intercambio de mensajes.

Base teórica

El diseño comienza con la definición de objetivos y restricciones. El objetivo principal no radica en desarrollar por desarrollar. Necesitamos obtener una herramienta segura y escalable, sobre la cual se puedan crear, y lo más importante, desarrollar aplicaciones modernas de diferentes niveles: desde aplicaciones en un solo servidor que atienden a una pequeña audiencia, que luego pueden evolucionar hacia clústeres de 50-60 nodos, hasta federaciones de clústeres. Así, el objetivo principal es maximizar las ganancias reduciendo el costo de desarrollo y posesión del sistema final.

Identifiquemos 4 requisitos principales para el sistema final:

  • Conorientación a eventos.
    El sistema siempre está listo para dejar pasar un flujo de eventos y realizar las acciones necesarias;
  • Mescalabilidad.
    Los bloques individuales pueden escalar tanto vertical como horizontalmente. Todo el sistema debe tener la capacidad de crecer horizontalmente de manera infinita;
  • Alta disponibilidad.
    Todos los niveles y todos los servicios deben tener la capacidad de recuperación automática ante fallos;
  • Garantía de tiempo de respuesta.
    El tiempo es valioso y los usuarios no deben esperar demasiado tiempo.

Recuerda el antiguo cuento de “El pequeño motor que pudo”, también conocido como “El trenecito que pudo”? Para que el sistema diseñado salga exitosamente de la fase de prototipo y sea progresivo, su fundamento debe satisfacer requisitos mínimos. PUDO.

Al mensajería como una herramienta de infraestructura y base para todos los servicios se añade otro punto: la facilidad de uso para los programadores.

Orientación a eventos

Para que una aplicación pueda crecer de uno servidores a un clúster, su arquitectura debe asegurar un bajo acoplamiento. Este requisito es satisfactorio para el modelo asíncrono. En él, el remitente y el destinatario se ocupan de la carga informativa del mensaje y no se preocupan por la transmisión y enrutamiento dentro del sistema.

Escalabilidad

La escalabilidad y la eficiencia del sistema van de la mano. Los componentes de la aplicación deben ser capaces de utilizar todos los recursos disponibles. Cuanto más eficientemente podamos utilizar la capacidad y cuantas más óptimas sean nuestras técnicas de procesamiento, menos dinero gastaremos en hardware.

Dentro de una sola máquina, Erlang crea un entorno de alta concurrencia. El equilibrio entre concurrencia y paralelismo se puede establecer eligiendo la cantidad de hilos del sistema operativo disponibles para la VM de Erlang y el número de planificadores que utilizan esos hilos.
Los procesos de Erlang no tienen estado compartido y funcionan en modo no bloqueante. Esto garantiza una latencia relativamente baja y un mayor rendimiento en comparación con las aplicaciones tradicionales construidas sobre sincronización bloqueante. El planificador de Erlang se encarga de la distribución justa de CPU e IO, y la ausencia de bloqueos permite que la aplicación responda incluso en modo de carga máxima o fallos.

A nivel de clúster, también existe un problema con la utilización. Es importante que todas las máquinas del clúster estén equilibradamente cargadas y que la red no esté sobrecargada. Imaginemos la situación: el tráfico de usuarios llega a los balanceadores de carga entrantes (haproxy, nginx, etc.), los cuales distribuyen las solicitudes para su procesamiento de la manera más equitativa posible entre un grupo de backend disponibles. Dentro de la infraestructura de la aplicación, el servicio que implementa la interfaz requerida es solo la última milla, y necesitará solicitar varios otros servicios para responder a la solicitud inicial. Las solicitudes internas también requieren enrutamiento y balanceo.
Para gestionar eficazmente los flujos de datos, el mensajería debe proporcionar a los desarrolladores una interfaz para gestionar el enrutamiento y la distribución de la carga. Gracias a esto, los desarrolladores podrán resolver tanto tareas estándar como situaciones raras utilizando patrones de microservicios (agregador, proxy, cadena, ramificación, etc.).

Desde el punto de vista empresarial, la escalabilidad es una de las herramientas de gestión de riesgos. Lo más importante es satisfacer las solicitudes de los clientes, utilizando el hardware de manera óptima:

  • Al aumentar la potencia del hardware como resultado del progreso. No quedará ocioso debido a defectos del software. Erlang se escala verticalmente de manera excelente y siempre podrá aprovechar todos los núcleos de CPU y la memoria disponible;
  • En entornos de nube, podemos gestionar la cantidad de hardware según la carga actual o prevista y garantizar el SLA.

Tolerancia a fallos

Consideremos dos axiomas: "Las fallas son inaceptables" y "Las fallas siempre ocurrirán". Para los negocios, un fallo de software significa pérdida de dinero y, aún peor, pérdida de reputación. Al equilibrar las posibles pérdidas y el costo de desarrollar software tolerante a fallos, a menudo se puede encontrar un compromiso.

A corto plazo, una arquitectura que incluye la tolerancia a fallos ahorra dinero en la compra de soluciones de clustering listas. Son costosas, y también tienen errores.
A largo plazo, una arquitectura tolerante a fallos recupera con creces los costos de su implementación en todas las etapas del desarrollo.
La mensajería dentro de la base de código aún se encuentra en desarrollo, lo que permite trabajar en detalle la interacción de los componentes dentro del sistema. Esto facilita la tarea de respuesta y gestión de fallos, ya que todos los componentes responsables manejan fallos y el sistema final sabe cómo recuperarse automáticamente tras una falla por diseño.

Reactividad

Independientemente de las fallas, la aplicación debe responder a las solicitudes y cumplir con el SLA. La realidad es que la gente no quiere esperar, por lo tanto, el negocio debe adaptarse. Se espera una alta reactividad de un número cada vez mayor de aplicaciones.
Las aplicaciones reactivas funcionan en un modo cercano al tiempo real. La Erlang VM opera en un modo de tiempo real suave. Para ciertos campos, como el comercio bursátil, la medicina y la gestión de equipos industriales, es crucial un modo de tiempo real estricto.
Los sistemas reactivos mejoran la experiencia del usuario y son útiles para los negocios.

Conclusiones preliminares

Al planear este artículo, quería compartir mi experiencia en la creación de un broker de mensajería y en la construcción de sistemas complejos sobre su base. Sin embargo, la parte teórica y motivacional resultó ser bastante extensa.
En la segunda parte del artículo, hablaré sobre los matices de la implementación de puntos de intercambio, patrones de mensajería y su aplicación.
En la tercera parte, abordaremos cuestiones generales sobre la organización de servicios, enrutamiento y balanceo. Hablaremos sobre el aspecto práctico de la escalabilidad y la resiliencia de los sistemas.

Fin de la primera parte.

Foto @lucabravo.

Fuente: habr.com

Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS 🔥 Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS | ProHoster