Al crear un servicio de back-end, ¿cómo puedo asegurarme de que se pueda ampliar para admitir 1 millón de usuarios desde el primer día?

Comience con un lenguaje rápido en el servidor, minimice el trabajo que el servidor necesita hacer y diseñe una infraestructura fácilmente escalable.

Si el escalado es una preocupación importante, pero comienzas tu código en PHP o Ruby, lo siento, pero lo estás haciendo mal. Y sí, mucha gente predica lo que considero la respuesta incorrecta aquí. También creo que la escritura estática es crucial para el código sólido. [1] Parte de esto viene de intentar las cosas de otra manera. Llevo 30 años desarrollando software. He intentado muchos enfoques y me he encontrado con muchos problemas. Esta es mi sabiduría actual sobre el tema, en resumen.

Sí, puede escalar horizontalmente idiomas más lentos, pero eso puede ser difícil de hacer bien, y tiende a dar a algunos usuarios una experiencia deficiente (latencia incorrecta, tal vez incluso errores, mientras aumenta la capacidad). Cuando cada servidor puede manejar 40 veces más clientes o más, el escalado puede ocurrir con mucha menos frecuencia, y si implementa el escalado automático, hay mucho más búfer entre un servidor que está medio lleno y saturado.

Mira a Quora. Han estado luchando una batalla con la escala durante meses. Periódicamente no puedo guardar un comentario o respuesta porque sus servidores no responden. Escuché que su parte trasera es Python. Claramente tiene problemas recurrentes. Algo de eso podría ser la capa de base de datos, que también debe ser escalable.

Para el lenguaje que maneja su lógica de back-end, llegar a un millón de “usuarios”, Go es probablemente su mejor opción. Dependiendo de los patrones de uso, podría manejar tantos en un servidor. Si te refieres a un millón todos conectados a la vez , probablemente necesites un poco de escala horizontal.

Go probablemente puede proporcionar respuestas de 10–40k por segundo para la lógica de servidor típica en un buen hardware. Si sus millones de usuarios se conectan en el transcurso de unos minutos, incluso el extremo inferior de ese rango podría manejar a un millón de usuarios, incluso si fuera una carga, pero la carga de Internet tiende a ser fractal, por lo que probablemente querría más capacidad si está inactivo la mayor parte del tiempo para manejar cargas máximas.

Reducir su necesidad de servidores de back-end es otra estrategia para llevar a la mesa. Haga todo el trabajo posible en el cliente. Use un marco de cliente como Angular, React o Vue.js, para que el navegador esté haciendo el trabajo de la plantilla. Y por amor a todo lo bueno, coloque archivos estáticos en un CDN. Sí, Go puede servir muchos archivos de un sistema, pero realmente desea utilizar su capacidad y ancho de banda para algo que una CDN no puede hacer mejor.

Si tiene una tarea de servidor que requiere una cantidad considerable de tiempo de procesamiento (conversión de imágenes o algo), entonces probablemente quiera usar un enfoque “sin servidor” como Amazon lambda. Entonces Amazon puede manejar la escala por usted.

En cuanto a las bases de datos: algunas escalan horizontalmente mejor que otras. Haga su tarea y descubra qué base de datos maneja los patrones de acceso que necesita. [2] Cambie la escala de sus servidores de bases de datos al nivel en que puedan admitir los patrones de acceso que necesita. El escalado automático de grandes bases de datos lleva tiempo, así que no esperes poder aumentar más la capacidad en un abrir y cerrar de ojos.

O Google Cloud Storage [3] puede ser adecuado para usted; deja que Google se encargue del escalado, y solo pagas por la capacidad y el ancho de banda.

Buena suerte.

Notas al pie

[1] Tipos estáticos considerados útiles · RealMensch

[2] Cassandra vs MongoDB vs CouchDB vs Redis vs Riak vs HBase vs Couchbase vs Hypertable vs ElasticSearch vs Accumulo vs VoltDB vs Scalaris comparación

[3] Almacenamiento en la nube: almacenamiento de datos en línea | Google Cloud Platform

Como dicen algunas personas. No es necesariamente una buena idea comenzar por querer manejar ese número. Hay muchas historias de terror sobre startups que no podrían escalar lo suficientemente rápido. Pero si su servicio es popular, entonces tiene espacio para hacerlo más tarde, incluso si la gente se queja (mire Twitter, por ejemplo).

Sin embargo, creo que hay una cosa que puede hacer … desde el principio, que es bastante barata, pero que lo preparará para escalar: piense en su sistema como una serie de “microservicios” independientes a los que se unen colas asincrónicas .

No cuesta mucho más escribir tres servidores pequeños en lugar de uno grande. O para poner explícitamente colas de mensajes entre diferentes partes principales de funcionalidad de su sitio en lugar de hacer que se comuniquen a través de la misma base de datos o llamadas a procedimientos remotos sincrónicos de una parte a otra.

Por lo tanto, planifique desde el principio la transmisión de mensajes y ningún estado compartido entre los grandes componentes arquitectónicos de su sistema. Esto hará que el escalado sea mucho más fácil cuando sea necesario.

Utilice metodologías de aplicaciones modernas, también conocidas como aplicaciones de 12 factores.

Lo más importante, el desarrollo de su aplicación debe ser independiente de la escala o la infraestructura. En segundo lugar, debe conocer el cuello de botella (generalmente el almacenamiento de estado como las bases de datos) y tener capacidades de escalabilidad allí.

Esto es posible a través de plataformas como Kubernetes. Puede escalar entidades abstractas sin preocuparse por la infraestructura subyacente. Una vez que agrega un nodo a su clúster, las entidades se redistribuyen en todo el clúster. Esto es muy poderoso, ya que la forma en que construye su aplicación para un solo usuario es la misma que la construiría para millones de usuarios.

Como ingeniero en Hasura, hemos tenido un éxito inmenso al adoptar Kubernetes como la plataforma para desplegar aplicaciones que necesitan escalar a demanda.

Cada servicio de fondo debe ampliarse de forma diferente, según el tipo de servicio y el comportamiento del usuario. Si bien es bueno pensar en escalar desde el Día 1, es difícil implementarlo realmente. El primer paso obvio es diseñar el software para que funcione para 100–1000 usuarios sin problemas.

Junto con eso, le sugeriría que invierta tiempo en elegir un servicio de alojamiento escalable dinámicamente (para bases de datos, almacenamiento en caché, equilibrio de carga, etc.) y en el conjunto correcto de herramientas analíticas para monitorear las acciones de sus usuarios. Más tarde, cuando llegue a la mitad del camino (500k usuarios), piense en qué servicios son cuellos de botella y / o qué servicios usan más sus usuarios y realice modificaciones para ampliarlos.

También puedes echar un vistazo a cómo Dropbox manejó el escalado.

¡Espero que esto ayude!

Hay muchas sugerencias excelentes aquí en las otras respuestas, así que agregaré solo tres cosas …

Primero, desea que el costo del hardware se amplíe linealmente (o mejor) con la cantidad de usuarios. En otras palabras, si puede admitir usuarios X con $ Y en hardware, entonces debería poder admitir usuarios X * 10 gastando $ Y * 10 (o menos) en hardware.

Eventualmente, descubrirá un límite superior en la cantidad de usuarios que puede admitir con una sola unidad de hardware (donde la unidad podría ser un solo servidor o una pila de servidores en diferentes roles). Llamemos a ese número N. Desea mantenerse en una posición en la que siempre pueda admitir N usuarios adicionales mediante el despliegue de una unidad adicional.

Mientras diseña su servicio, esté atento a las cosas que se escalan más que linealmente con la cantidad de usuarios. Si encuentra algo que se escala con el cuadrado de usuarios, o con el factorial de usuarios, tiene un problema. Tal vez pueda encontrar un nuevo diseño que no tenga ese problema. Tal vez no pueda, pero puede dividir a sus usuarios para que el problema siga siendo manejable. O tal vez tampoco pueda hacerlo, y necesita presupuestar para un aumento rápido en los costos de almacenamiento / ancho de banda / cálculo … pero realmente no desea encontrarse en esa posición.

Segundo, diseñe el monitoreo en su sistema desde el principio. Debería tener un tablero en algún lugar que le diga qué tan saludable es su sistema, por servidor o por componente o por ubicación. Mida el consumo de ancho de banda, las latencias, las tasas de error, las tasas de transacción, etc.

El teléfono de alguien debe sonar cuando las tasas de error aumentan por encima del X%, y cuando la latencia del percentil 99 aumenta por encima de Xms, y así sucesivamente.

Por último, pero no menos importante … El número de veces que se llama a alguien cada mes debe permanecer constante a medida que agrega usuarios. Es bastante simple arrojar dinero a los proveedores de hardware cuando necesita capacidad de servicio, pero es mucho menos simple arrojar dinero a los seres humanos cuando necesita más capacidad de lucha contra incendios.

Los desarrolladores de software generalmente odian estar de guardia (incluido yo mismo), pero alinea muy bien los incentivos. Las personas a las que se busca deben estar habilitadas para realizar cambios en el código para evitar páginas adicionales en el futuro. Y, por extensión, sus gerentes no deben estar facultados para priorizar nada más que la estabilidad del servicio.

  • Caché HTTP. Esto sería del # 1 al # 10 en mi libro. Puede hacer todo lo demás correctamente y aún así ser eliminado porque no diseñó la aplicación / servicio para aprovechar esto.
  • Comprender la complejidad de tiempo / espacio (las grandes O) de varios algoritmos y estructuras de datos para el trabajo.
  • Diseño para concurrencia en mente, especialmente a nivel de base de datos.
  • Establezca los planes para escalar sus recursos IaaS / PaaS rápidamente, si no de manera automática.
  • Pruebas de carga en todas las capas.

A menos que espere que 1. millón de usuarios se pongan en marcha el primer día, no tiene sentido tener una aplicación que pueda manejar 1 millón de usuarios el primer día.

En cuanto a la ampliación, según sea necesario, de nuevo … en parte depende de cuán “listo” realmente necesite estar.

En los proyectos de couepf, aconsejo que “diseñemos para escalar, implementemos por ahora” … en otras palabras, nuestro diseño general tiene en cuenta el hecho de que podemos querer escalar la aplicación verticalmente (obtener un servidor más grande) u horizontalmente (obtener muchos servidores y distribuir la carga a través de ellos).

Entonces … incluso con un servicio relativamente lento (tal vez escrito en php) podemos usar el escalado horizontal para soportar cargas inesperadas … pero estamos listos para volver a implementar servicios (y usaremos Go) cuando realmente necesitemos escala y rendimiento.

Escriba su aplicación como si fuera una batería que se puede cambiar fácilmente. Eso significa reducir los datos fijos para que puedan moverse de un servidor a otro. Reduzca la cantidad de datos que deben procesarse en cada solicitud. Esto significa emplear estructuras de bases de datos inteligentes y algoritmos de lectura. Datos de caché que no necesitan actualizarse sobre la marcha.

¿1 millón de usuarios al mismo tiempo?
1 millón de usuarios por día?
1 millón de usuarios en total?

Necesita decidir lo que necesita / quiere / espera. Para los dos primeros, debe considerar el equilibrio de carga; para el tercero, suficiente espacio de almacenamiento.

Seguro que ayuda mucho si construyes en una plataforma escalable. es decir, AWS, especialmente AWS Lambda. Aún debe ser inteligente sobre los cuellos de botella, pero una plataforma en la nube puede manejar muchos de los posibles cuellos de botella por usted.