Automatch / jugadores en cola

8

Estoy usando Node.js y Redis. Estoy tratando de encontrar una forma confiable de atrapar jugadores automáticamente. Hay un servidor coincidente y luego se configuran varios servidores de juegos.

Lo siguiente es lo que necesito que suceda:

  1. El jugador envía una solicitud de ingreso con el tipo de juego (pequeño / mediano, etc.)
  2. El servidor coincidente agrega al jugador al tipo de juego actual que está esperando a los jugadores
  3. El servidor del juego envía al jugador la ID del juego

Actualmente lo he implementado de la siguiente manera:

  1. El servidor coincidente escucha el juego: cola: pequeña usando BRPOP
  2. Comprueba si el juego: cola: pequeño: id = id existe
  3. Comprueba si el juego: id: la longitud de los usuarios es <= 6 (jugadores máximos)
  4. Agrega jugador al juego: id: lista de usuarios si es
  5. Si la duración del juego ahora es 6, elimina game: queue: small: id

Si el servidor coincidente encuentra game: queue: small: id falta, hace lo siguiente:

  1. Juego INCR: nextGameId
  2. Establece game: queue: small: id a la ID generada previamente
  3. Agrega el ID del juego al juego: cola: esperando

Los servidores del juego esperan usar BRPOP para nuevos juegos. Cuando obtienen uno, esperan hasta que el juego tenga un mínimo de 2 usuarios y luego inician un temporizador. Si no se llenan en ese tiempo, comienzan con los usuarios que tienen y luego eliminan game: queue: small: id (lo que obliga al matchmaker a solicitar un nuevo juego).

Mientras mi método funciona, no estoy convencido de que funcione bien en la producción y parece muy complicado. Puedo ver el potencial de los siguientes problemas:

  • El servidor del juego se bloquea después de aceptar la ID del juego de la lista de espera, lo que hace que los usuarios se agreguen al juego: id: usuarios pero no sucede nada con ellos (el bloqueo en sí no es un problema, pero los usuarios que continúan agregándose a esa cola de juegos es )
  • Si un usuario se desconecta y el juego no ha comenzado, el servidor del juego eliminará al usuario del juego: id: lista de usuarios. Mientras está en el proceso de hacer eso, el servidor de emparejamiento podría estar agregando un usuario a la lista y pensar que el juego está lleno, eliminándolo de la cola.

Mis pensamientos iniciales fueron cambiar a una sola cola de usuarios que esperaban un tipo de juego. Sin embargo, esto presenta más problemas:

  • Si el servidor al que se conectan los usuarios se bloquea, no eliminará al usuario de la cola y, por lo tanto, dejará que ese usuario ingrese a un juego cuando no exista. Podría usar conjuntos ordenados para almacenar el tiempo de la solicitud y hacer que el cliente realice una encuesta hasta que se devuelva una ID del juego, pero esto significaría que no tengo idea de cuánto tiempo ha esperado ese cliente y, por lo tanto, no sé si iniciar el juego con menos usuarios
  • Sin poner a los usuarios en un juego, no tienen la capacidad de ver a qué usuarios se han unido, ni tienen la posibilidad de chatear con los usuarios que están esperando (ya que eso requiere una identificación del juego).

Ninguna de las formas en que he configurado esto se siente bien, así que esperaba que alguien pudiera ofrecer algunas sugerencias mejores. Realmente necesito mantener separados los servidores del juego y los servidores de emparejamiento para poder crecer según sea necesario.

Chris Evans
fuente
El problema de la base de datos que he resuelto aquí: stackoverflow.com/questions/15172556/…
Chris Evans
En Comprueba si el juego: cola: pequeño: id = id existe , ¿cómo se obtiene el ID?
Rayón

Respuestas:

1

Su primer y principal error es usar una base de datos para una cola en vivo, es mucho mejor almacenar los datos en la memoria del proceso en el proceso de emparejamiento. Deje que los procesos se comuniquen entre sí directamente. Entonces también es bastante forzado para ti que es responsabilidad exclusiva del servidor de emparejamiento eliminar a los jugadores de la cola cuando se ponen en un juego, como debería ser.

En términos más generales sobre emparejamiento, retrase las decisiones de qué partidos exactos hacer hasta el punto donde comienza el juego, si tiene 3 jugadores que encajan en un juego de 4 jugadores, no decida que tienen que jugar ese tipo de juego antes de que haya también un cuarto jugador, podría tomar mucho tiempo para que llegue ese jugador, y algunos de ellos podrían dejar de esperar mientras tanto. Una implementación decente para esto es tener una cola para cada tipo de juego y poner a cada jugador en todas las colas que coincidan con su solicitud, luego, cuando una cola esté llena, comience el juego y elimine a los jugadores involucrados de todas sus colas.

aaaaaaaaaaaa
fuente
Estaba usando Redis como maneja bien las colas. Inicialmente administraba el emparejamiento dentro del propio servidor y funcionó muy bien, pero encontré dos problemas con este enfoque: no pude encontrar una forma de escalarlo y, en segundo lugar, cómo solicita el servidor que se inicie un nuevo juego en otro servidor. ¿Podría enviarles un mensaje a todos pero la carga no se equilibraría?
Chris Evans
1
@ChrisEvans No debes preocuparte demasiado por escalar, un simple proceso de emparejamiento puede manejar miles de iniciaciones de juego por segundo. Si solo lo codifica bien, no necesitará el emparejamiento para escalar a múltiples procesos, incluso si obtiene millones de clientes. En cuanto al equilibrio de la carga en los servidores de juegos, un enfoque simple de round robin donde cada servidor de juegos obtiene un nuevo juego a su vez es razonablemente efectivo si los servidores generalmente pueden manejar una gran cantidad de juegos cada uno. De lo contrario, puede preguntar periódicamente a los servidores del juego qué tan ocupados están, no tiene que suceder una vez por juego nuevo.
aaaaaaaaaaaa