¿Cuáles son algunos de los conceptos fundamentales de infraestructura escalable?

Grokked por experiencia:

  • Embotellamiento
    ¿Qué parte del sistema consume / retiene la mayoría de los recursos (CPU, memoria, E / S, bloqueos de grano grueso)? El rendimiento de un sistema es tan bueno como el rendimiento del cuello de botella.

    Soluciones: apatridia (externalizar el estado a capas más distribuidas, por ejemplo, cliente o capa de datos), almacenamiento en caché (antigüedad de datos comerciales por rendimiento), especialización (separación del sistema en servicios / grupos funcionales bastante independientes), fragmentación (división / distribución del trabajo por espacio de datos) , replicación y equilibrio de carga (para distribuir recursos. Las variaciones son replicación maestro-esclavo, 1 escribe N lee la replicación, W escribe R lee la replicación), consistencia eventual (intercambiando consistencia fuerte para alta disponibilidad), concurrencia optimista y estado blando (aislamiento comercial para alta disponibilidad)

  • Punto único de fallo
    Si muere, todo lo demás muere. Un sistema es tan confiable como su único punto de falla.

    Soluciones: Replicación (para lograr una mayor disponibilidad), por ejemplo, con el quórum del cuidador del zoológico (generalmente utilizado como autoridad central para coordinar operaciones distribuidas, descubrimiento de nodos, etc.).

  • Bajo acoplamiento
    (para administrar actualizaciones independientes de diferentes servicios / capas. Un error común es hacer que las cosas estén tan estrechamente tejidas que para actualizar una capa necesitarás derribar toda la aplicación. Parece mágico al principio, como el infierno más tarde. Eso es por qué tratar de evitar marcos estrechamente acoplados )

    Soluciones: servicización , estratificación , dependencia unidireccional (permite actualizaciones individuales sin interrupción), desacoplamiento a nivel de tiempo de ejecución (por ejemplo, mediante el uso de colas de mensajes. La idempotencia se vuelve importante para tolerar mensajes duplicados o reintentos en general)

  • Manejabilidad
    (para salvar tu cordura en general)

    ¿Cómo se nombran los nodos / servicios? ¿Cómo se le notifica que los nodos mueren o cobran vida? ¿Cómo agrega o elimina máquinas de un clúster? ¿Cómo se nombran los grupos? ¿Qué servicio es la principal autoridad para la verdad? ¿Cómo sé qué versiones de código ejecuta cada nodo? ¿Cómo se correlaciona lo que sucedió aquí con lo que sucedió allí?

Componentes comunes:

  • Remoting (usando TCP / HTTP, varias selecciones de serializaciones)
  • Equilibrio de carga (round-robin, aleatorio, sesión fija)
  • Cola de mensajes
  • Almacenes de datos distribuidos
  • Zookeeper
  • Sistema de monitoreo (invierta temprano para prevenir el dolor de cabeza más adelante, confíe en mí)

Otras cualidades arquitectónicas que de repente se vuelven importantes con la escala:

  • Confiabilidad y tolerancia a fallas: porque el tiempo esperado para fallar se acorta drásticamente a medida que agrega más nodos. Necesidad de construir sistemas que sean inmunes a las fallas de los nodos regulares. Debe prestar más atención a las copias de seguridad periódicas y la replicación en vivo para copias de seguridad a corto plazo.

La escalabilidad no es una propiedad booleana

No puede decir que un sistema “es escalable” o “no es escalable”. Lo más que puede decir es que, bajo ciertas condiciones, es escalable a lo largo de ciertas dimensiones, hasta cierto punto. Las prácticas de escalabilidad que funcionan para una compañía de 10 personas no funcionarán para una compañía de 1,000 personas, y la base de datos que escala a 100 consultas por segundo y gigabytes de datos no escalará a 10,000 consultas por segundo y petabytes de datos. Esta es la razón por la cual las startups pequeñas no deberían intentar adoptar las prácticas de escalabilidad de Google y por qué las empresas masivas no deberían intentar adoptar las prácticas de escalabilidad de startups.

A veces, está bien hacer cosas que no escalan

Este es el consejo clásico de Y Combinator: cuando comienzas algo pequeño, Hacer cosas que no escalan puede ser una ventaja. Esto se debe a que el mayor riesgo en los nuevos proyectos no es que construyas algo de la manera incorrecta y termines abrumado por millones de usuarios, sino que construirás algo incorrecto y no obtendrás ningún usuario. Invertir en hacer que los productos y la infraestructura sean más escalables lleva mucho tiempo, por lo que poder omitir eso en las primeras etapas de desarrollo, mientras todavía está determinando si lo que tiene vale la pena escalar, es una gran ventaja. Consulte Un producto mínimo viable no es un producto, es un proceso para obtener más información.

Es probable que tenga que escalar las prácticas de codificación antes que el código mismo

La mayoría de las empresas enfrentan cuellos de botella en la forma en que escriben el código mucho antes de llegar a los cuellos de botella en lo que realmente hace el código. A medida que su equipo y la base de códigos crezcan, rápidamente llegará a una etapa en la que la reparación de un error causa dos más, las liberaciones son dolorosas y propensas a errores, las interrupciones son frecuentes y su capacidad para enviar códigos se detiene casi por completo. En esta etapa, tendrá que invertir en escalar sus prácticas de codificación a través de pruebas automatizadas, integración continua, revisiones de código, modularización de código, documentación, etc. Echa un vistazo a Agility Requiere Seguridad para más información.

Escalabilidad común y patrones de rendimiento

No existe una solución única para mejorar la escalabilidad y el rendimiento. Dicho esto, hay una serie de patrones que ocurren con frecuencia:

  • Divide y vencerás : divide un problema en muchos problemas más pequeños y resuelve los problemas en muchas CPU o servidores para que cada uno tenga que hacer menos trabajo. Ejemplos: múltiples servidores web, replicar o fragmentar una base de datos, MapReduce.
  • Almacenamiento en caché : haga el trabajo con anticipación y guarde los resultados, de modo que en lugar de calcularlos a pedido, solo recupere los valores calculados previamente del almacenamiento. Ejemplos: cachés de bases de datos, esquemas desnormalizados, cachés distribuidos, CDN, cookies, memorización, algoritmos de programación dinámica.
  • Pereza : Evite hacer el trabajo posponiéndolo hasta que sea absolutamente necesario. Ejemplos: partes de carga lenta de una página web solo cuando se desplaza a ella, bloqueo optimista en una base de datos.
  • Corrección aproximada : en muchos casos, se necesita menos trabajo para obtener una respuesta que sea “lo suficientemente cercana” como para obtener una que sea exactamente correcta. Ejemplos: consistencia eventual, HyperLogLog, garantías de durabilidad reducida, mensajes de mejor esfuerzo.
  • Asincronía : en lugar de bloquear o bloquear mientras espera el resultado de un cálculo, continúe trabajando y haga que el cálculo le notifique cuando haya terminado. Ejemplos: E / S sin bloqueo, bucles de eventos, estructuras de datos sin bloqueo.
  • Jitter y aleatorización : evite picos y puntos calientes tratando de distribuir la carga de manera uniforme. Ejemplos: aleatorización de fechas de caducidad de caché, algoritmos de equilibrio de carga (round robin, programación de prioridad), algoritmos para la partición de claves (por ejemplo, partición de rango, partición de hash).
  • Aceleración : rechace ciertos cálculos para que no ralenticen otros. Ejemplos: solicitudes de limitación de velocidad en un servidor o eliminación de servidores lentos de la ruta de solicitud.
  • Redundancia : inicie el mismo cálculo más de una vez y devuelva el que termine más rápido. Ejemplos: solicitudes de respaldo o cubiertas en sistemas distribuidos, servidores redundantes en caso de falla (por ejemplo, espera activa para una base de datos).
  • Co-ubicación : acerque las cosas físicamente para reducir la latencia. Ejemplos: CDN, múltiples centros de datos en todo el mundo, colocando servidores relacionados en el mismo rack de servidores.
  • Hardware más rápido : escala vertical AKA. Ejemplos: CPU más rápida, más RAM, más caché de CPU, discos duros de estado sólido, redes más rápidas, realizar cálculos en RAM en lugar de en disco o en el caché de CPU en lugar de en RAM.
  • Algoritmos más rápidos : encuentre un algoritmo que le permita hacer menos trabajo. Ejemplos: búsqueda binaria en lugar de búsqueda lineal, ordenación rápida en vez de burbuja.

(La lista anterior se copia del Capítulo 7, Escalabilidad, de mi libro Hello, Startup: A Programmer’s Guide to Building Products, Technologies, and Teams )

Otras lecturas

La escalabilidad es un gran tema. Estos son algunos de mis recursos favoritos para aprender más:

  • La aplicación de los doce factores
  • Una guía completa para crear una aplicación web escalable en Amazon Web Services
  • Recursos de inicio: escalabilidad
  • Principios de los programas de alto rendimiento.
  • Diseño de aplicaciones intensivas en datos
  • Números que todo programador debe saber
  • Hola, Startup: una guía del programador para crear productos, tecnologías y equipos

Mi respuesta a esta pregunta es ampliamente aplicable a todos los idiomas:

https://www.quora.com/Python-programming-language-1/What-are-the-best-components-for-creating-scalable-Python-web-applications/answer/Vaibhav-Mallya

Obviamente, algunos pequeños detalles cambian en función de la pila exacta que está utilizando (por ejemplo, Hibernate o Spring en lugar de SQLAlchemy), pero los detalles y conceptos de alto nivel siguen siendo sólidos.

Hay algunos conceptos fundamentales que se requieren cuando se construye una arquitectura escalable.

Primero, tendrá que hacer que el acceso front-end a su servicio web sea escalable mediante solicitudes de equilibrio de carga en múltiples servidores web. Este proceso es sencillo en un sistema sin estado, pero suponiendo que desee garantizar el estado en múltiples solicitudes a múltiples servidores web, es posible que deba considerar cómo compartirá este estado de manera escalable.

En segundo lugar, deberá considerar las fuentes de datos con las que interactuará el código en estos servidores web. Normalmente esto incluye servidores RDBMS o NoSQL, y dependiendo de la plataforma de servidor que elija, necesitará comprender las arquitecturas de escala específicas de esa plataforma.

Finalmente, debe considerar una solución de almacenamiento en caché si se ajusta a los requisitos de su aplicación para que pueda minimizar la carga en sus fuentes de datos cuando no es necesario estresarlas.

  • TCP / IP, HTTP, SSL
  • Conveniencia de los métodos idempotentes y sin estado
  • Almacenamiento en caché
  • Gestión de configuración de servidores y equilibrio de carga
  • Teorema CAP en el lado de datos
  • Seguridad web
  • Monitoreo y recopilación de métricas de servidor. Análisis de datos de la máquina.

Por ahora, dejemos de lado las cuestiones de ancho de banda de red y espacio físico y centrémonos únicamente en la arquitectura de software. El mejor enfoque inicial es considerar todos y cada uno de los componentes de la arquitectura del software y garantizar que cada componente, cada capa, se pueda ampliar fácilmente.

Dado que los servicios web viven en servidores web, la primera consideración es si se pueden agregar servidores web adicionales a la infraestructura para servir el mismo contenido de servicio web sin ningún cambio de código. Mientras los servicios web se hayan escrito de tal manera que no tengan estado, esto no debería ser un problema. Afortunadamente, los servicios web generalmente son apátridas porque simplemente actúan como una imitación entre un cliente y sus datos de back-end. Por lo tanto, si sus servidores web que alojan sus servicios web se están bloqueando, simplemente agrega más servidores y, voila, tiene más capacidad.

La parte más difícil es descubrir cómo escalar los datos de back-end con estado. Hay tres caminos aquí, y no son mutuamente excluyentes. 1) Divida su base de datos de back-end en conjuntos de datos con estado o sin estado. Las cosas sin estado (generalmente los datos de solo lectura) se pueden replicar a cualquier cantidad de bases de datos esclavas con solo los conjuntos de datos que se pueden escribir que se ejecutan en un servidor de base de datos robusto. 2) Haga todo lo posible para mejorar el rendimiento del servidor de base de datos único que ejecuta el conjunto de datos con estado, desde ajustes de software como optimizar la configuración de la base de datos y agregar índices a mejoras de hardware como usar unidades más rápidas (SSD), mejores controladores RAID, agregar más RAM , e intercambiando CPUs más / más rápidas. 3) Introducir software intermediario que mejore la capacidad de respuesta a través de trucos de almacenamiento en caché de escritura, como guardar escrituras en memoria y luego realizar confirmaciones en lote después del hecho. Todo tipo de inteligencia se puede lograr con herramientas como beanstalk y memcache, entre otras.