tutorial principiantes para nodejs node libro home desde certificacion cero javascript node.js sockets scalability autoscaling

javascript - principiantes - node js server



¿Cuál es la mejor manera de escalar mi aplicación nodejs? (2)

Los basicos

En este momento, algunos de mis amigos y yo estamos tratando de desarrollar un juego de navegador hecho en nodejs. Es un juego de disparos multijugador de arriba hacia abajo, y la mayoría del código tanto del lado del cliente como del lado del servidor está en javascript. Tenemos una buena dirección general a la que nos gustaría acceder, y nos estamos divirtiendo mucho desarrollando el juego. Uno de nuestros objetivos al hacer este juego fue hacer lo más difícil posible para hacer trampa. Hagan eso, tenemos toda la lógica del juego manejada en el lado del servidor. El cliente solo envía su entrada al servidor a través del socket web, y el servidor actualiza el cliente (también el socket web) con lo que está sucediendo en el juego. Aquí está el comienzo de nuestro problema.

Todas las matemáticas del lado del servidor se están volviendo bastante considerables, y estamos descubriendo que tenemos que escalar de alguna manera para manejar algo más de 10 jugadores (queremos poder alojar a muchos más). Al principio, pensamos que podíamos escalar verticalmente como lo necesitábamos, pero dado que nodejs tiene un solo hilo, solo puede aprovechar un núcleo. Esto significa que obtener un servidor más robusto no ayudará a ese problema. Nuestra única solución es escalar horizontalmente.

Por qué estamos preguntando aquí

No hemos podido encontrar ningún buen ejemplo de cómo escalar un juego nodejs. Nuestro caso de uso es bastante particular, y aunque hemos hecho todo lo posible para hacerlo por nuestra cuenta, realmente podríamos beneficiarnos de opiniones y consejos externos.

Detalles

Ya hemos pensado mucho sobre cómo resolver este problema. Hemos estado trabajando en eso por más de una semana. Esto es lo que hemos reunido hasta ahora:

Cuatro tipos de servidores

Estamos dividiendo tareas en 4 diferentes ''tipos'' de servidores. Cada uno tendrá una tarea específica que completará.

El servidor proxy

El servidor proxy se ubicaría al frente de toda la pila, y sería el único servidor al que se puede acceder directamente desde Internet (potencialmente podría haber más de estos). Tendría haproxy en él y enrutaría todas las conexiones a los servidores web. Elegimos haproxy por su gran conjunto de características, fiabilidad y velocidad casi insuperable.

El servidor web

El servidor web recibiría las solicitudes web y serviría todas las páginas web. También manejarían la creación / gestión de lobby y la creación / gestión de juegos. Para hacer esto, les dirían a los servidores del juego qué lobbies tiene, qué usuarios están en ese lobby e información sobre el juego que van a jugar. Los servidores web actualizarían los servidores del juego sobre la entrada del usuario, y el servidor del juego actualizaría los servidores web (que luego actualizarían a los clientes) de lo que está sucediendo en el juego. Los servidores web usarían sockets TCP para comunicarse con los servidores de juegos sobre cualquier tipo de administración, y usarían sockets UDP cuando se comuniquen sobre actualizaciones de juegos. Todo esto se haría con nodejs.

El servidor del juego

El servidor del juego manejaría todas las actualizaciones matemáticas y de juego del juego. Los servidores del juego también se comunican con los servidores de db para registrar estadísticas interesantes sobre los jugadores en el juego. Esto se haría con nodejs.

El servidor db

El servidor db alojaría la base de datos. Esta parte en realidad resultó ser la más fácil ya que encontramos rethinkdb , el mejor db de todos los tiempos. Esto se escala fácilmente, y por extraño que parezca, resultó ser la parte más fácil de escalar nuestra aplicación.

Algunos otros detalles

Si tiene problemas para familiarizarse con todo nuestro atuendo, mire esto , es una tabla semi-precisa de cómo creemos que escalaremos.

Si solo tiene curiosidad o cree que podría ser útil mirar nuestro juego, actualmente está alojado en su estado no escalado aquí.

Algunas cosas que no queremos

  • No deseamos utilizar el módulo de clúster de nodejs. No es estable (se dice here ), y no se escala a otros servidores, solo a otros procesadores. Nos gustaría dar el salto a la escala horizontal.

Nuestra pregunta, resumida

Esperamos que vayamos en la dirección correcta, y hemos hecho nuestra tarea, pero no estamos seguros. Sin duda, podemos tomar algunos consejos sobre cómo hacer esto de la manera correcta.

Gracias

Me doy cuenta de que esta es una pregunta bastante larga, y hacer una respuesta bien pensada no será fácil, pero realmente lo agradecería.

¡¡Gracias!!


Poco tarde para el juego, pero échale un vistazo aquí: http://goldfirestudios.com/blog/136/Horizontally-Scaling-Node.js-and-WebSockets-with-Redis

No mencionaste nada relacionado con la administración de la memoria. Como sabe, nodejs no comparte su memoria con otros procesos, por lo que una base de datos en memoria es imprescindible si desea escalar. ( Redis , Memcache , etc.) redis configurar un evento editor y suscriptor en cada nodo para aceptar solicitudes entrantes de redis . De esta forma, puede ampliar la cantidad de servidores x nilo (enfrente de su HAProxy) y utilizar los datos transmitidos desde redis .

También existe este complemento de node : http://blog.varunajayasiri.com/shared-memory-with-nodejs Eso le permite compartir memoria entre procesos, pero solo funciona bajo Linux. Esto ayudará si no desea enviar datos a través de procesos locales todo el tiempo o tiene que tratar con nodes ipc api.

También puede bifurcar los procesos hijo dentro del node para un nuevo aislamiento v8 para ayudar con las costosas tareas vinculadas a la CPU. Por ejemplo, los jugadores pueden matar monstruos y obtener un poco de botín dentro de mi juego RPG de acción. Tengo un proceso secundario llamado LootGenerater , y básicamente cada vez que un jugador mata a un monstruo envía el id del juego, mob_id y user_id al proceso a través del api .send IPC predeterminado. Una vez que el proceso hijo lo recibe, itera sobre la gran mesa de botín y gestiona los artículos (almacena en redis , o lo que sea) y lo canaliza hacia atrás.

Esto ayuda a liberar el ciclo de eventos en gran medida, y solo una idea en la que puedo pensar para ayudarte a escalar. Pero lo más importante es que deseará utilizar un sistema de base de datos en memoria y asegurarse de que la arquitectura de su código de juego esté diseñada según el sistema de base de datos que utilice. No cometa el error que tuve al tener que volver a escribir todo :)

¡Espero que esto ayude!

Nota: Si decides ir con Memcache, deberás utilizar otro sistema de pub / sub.


Siguiendo mis pensamientos espontáneos sobre tu caso:

Uso multinúcleo

node.js también puede escalar con múltiples núcleos. Cómo puede leer, por ejemplo, aquí ( o simplemente pensar en ello: tiene un hilo / proceso ejecutándose en un núcleo, ¿qué necesita para usar varios núcleos? Múltiples hilos o procesos múltiples. Empuje el trabajo del hilo principal a otros hilos o procesos y ya está hecho ).

Yo personalmente diría que es infantil desarrollar una aplicación que no utilice múltiples núcleos. Si utiliza algunos procesos en segundo plano, vale, pero si hasta ahora solo trabaja en el ciclo de eventos principales de node.js , definitivamente debe invertir algo de tiempo para hacer que la aplicación sea escalable sobre los núcleos.

Implementar algo así como IPC no es tan fácil por cierto. Puede hacerlo, pero si su caso es complicado, tal vez sea bueno ir con el módulo de clúster. Obviamente, este no es tu favorito, pero solo porque algo se llama "experimental" no significa que sea de mala calidad. Solo pruébalo, tal vez incluso puedas arreglar algunos errores del módulo en el camino. Lo más probable es que sea mejor utilizar un software ampliamente utilizado para problemas complejos, que inventar una rueda nueva.

También debería (si aún no lo hace) pensar en el uso (prudente) de la funcionalidad nextTick . Esto permite que el ciclo del evento principal pause algunas tareas intensivas de la CPU y realice otras tareas mientras tanto. Puede leer sobre esto, por ejemplo, aquí .

Pensamientos generales sobre cálculos

Definitivamente deberías echar un vistazo muy de cerca a tus algoritmos del motor del juego. Ya has notado que este es tu cuello de botella en este momento y en realidad los cálculos son la parte más crítica de la mayoría de los juegos. La escala resuelve este problema de una manera, pero la escala introduce otros problemas. Además, no puede lanzar "escala" como solucionador de problemas en todo y esperar que todos los problemas desaparezcan.

Su mejor apuesta es hacer que su código de juego sea elegante y rápido. Piense en cómo resolver problemas de manera eficiente. Si no puede resolver algo en Javascript de manera eficiente, pero el problema se puede extraer fácilmente, ¿por qué no escribir un pequeño componente C en su lugar? Esto también cuenta como un proceso separado, lo que reduce la carga en su ciclo principal de eventos node.js.

¿Apoderado?

Personalmente, no veo la ventaja del nivel de proxy en este momento. Parece que no esperas una gran cantidad de usuarios, por lo tanto, no necesitarás resolver problemas como CDN resuelve o lo que sea ... está bien pensarlo, pero no invertiría mucho tiempo allí en este momento.

Técnicamente, existe una gran posibilidad de que el software del servidor web proporcione la funcionalidad proxy de todos modos. Así que está bien tenerlo en el papel, pero no planificaría con hardware dedicado en este momento.

Epílogo

El resto me parece más o menos bueno.