¿Deberían un servidor de socket y un servidor de juego ser procesos separados?

14

Suponga un juego estándar simple de cliente / servidor. Para el servidor, ¿vale la pena tener un proceso separado que escuche las conexiones y los mensajes de los clientes y envíe los datos a través de sockets locales o stdin a otro proceso que ejecute el servidor del juego real?

La otra opción sería hacer ambas cosas en un solo proceso. Poner en cola los mensajes entrantes y ejecutarlos en el orden correcto no debería ser un problema detenido.

Me pregunto si los recursos adicionales para separar las dos "actividades" realmente valen la pena. ¿Cómo debo decidir? Me gustaría escuchar cualquier pros / contras.

luleksde
fuente
1
¿Cómo se comunican ambas partes? Enchufes?
vz0
¿Se imagina cambiando el "oyente" para usar una técnica de comunicación diferente, o agregando opciones para usar más de un tipo de comunicación cliente-servidor (por ejemplo, si los clientes móviles tenían que comunicarse de una manera diferente)? Si es así, puede valer la pena separarlo para que pueda intercambiar los módulos dentro / fuera según sea necesario.
Jon Story
@ JonStory Sí, lo hago. Sin embargo, incluso con 2 oyentes diferentes, podría ser un proceso único, pero después de leer todas las respuestas aquí y pensar un poco más al respecto, he decidido que valdrá la pena tener procesos separados. Para este proyecto en particular, el cliente principal será un navegador javascript, pero planeo agregar una aplicación de cliente móvil nativa en el futuro.
luleksde

Respuestas:

17

Desde la perspectiva del diseño de la API, al decidir si hacer múltiples programas de comunicación separados o solo uno, la pregunta es: ¿ puede cada programa funcionar significativamente sin los otros? La respuesta variará según su proyecto y sus preferencias.

Si no pueden , no vale la pena pensar en ello. Claramente están tan fuertemente vinculados que en realidad no son procesos separados.

Si pueden , y puede verse queriendo colocar diferentes componentes para reemplazarlos en el futuro, entonces una abstracción de proceso proporcionada por el sistema operativo podría ayudar.

Sin embargo, cuánto ayuda depende del resto de tu stack tecnológico. Por ejemplo, Erlang ya modela internamente las cosas como procesos, por lo que tampoco obtendrá un gran beneficio conceptual al dividirlo en procesos del sistema operativo. A menos que esté pensando en reescribir esas partes del servidor en un idioma diferente. Los componentes internos de un programa C ++ generalmente se acoplan mucho más y, por lo tanto, son más difíciles de intercambiar, por lo tanto, dividirlos en diferentes procesos del sistema operativo puede ahorrarle trabajo más adelante si puede prever tales reorganizaciones.

Anko
fuente
11

¿Vale la pena tener un proceso separado que escuche las conexiones y los mensajes de los clientes y envíe los datos a través de sockets locales o stdin a otro proceso que ejecute el servidor de juego real?

Para responder si vale la pena, primero tenía que preguntarse cuál es el problema que está tratando de resolver agregando un servicio de colas dedicado. Si resuelve ese problema, entonces vale la pena; si no resuelve un problema o si no tiene un problema para resolver, entonces probablemente no lo sea.

Veamos algunas razones por las que algunos servidores usan una arquitectura de varios niveles:

  1. Equilibrio de carga: el equilibrio de carga tiene sentido si desea distribuir su carga de trabajo a varias máquinas de trabajo. Si su programa tiene cuellos de botella que desea resolver simplemente al tener múltiples procesos de trabajo concurrentes en la misma máquina, entonces es mejor a largo plazo resolver el cuello de botella, pero como solución temporal a corto plazo, generar procesos de trabajo podría ser práctico.
  2. Separación de privilegios: tal vez no desee una violación de seguridad en su servidor de chat para acceder automáticamente a su servidor de juegos o viceversa. Si su servidor de juegos está separado de su servidor de chat en el juego, puede configurar su servidor de juegos y servidor de chat para vivir en un dominio de seguridad separado (por ejemplo, ejecutarlo como un usuario diferente, con diferentes privilegios de acceso, diferentes límites de proceso, etc.).
  3. Actualización de tiempo de inactividad cero: si desea lograr una actualización de tiempo de inactividad cero, debe tener varios niveles y configurar el sistema de modo que cuando elimine un servidor para dar servicio, sus solicitudes se redirigirán a los otros servidores en el mismo nivel para garantizar la continuidad Servicio.
  4. Límite de ruptura: si alcanza el límite de socket, el límite de descriptor de archivo, un bloqueo global de intérprete, etc., puede evitar ese límite ejecutando múltiples procesos. Otra forma de resolver esto es cambiar el límite, pero eso no siempre es fácil, ya que puede que tenga que volver a compilar el kernel, o puede haber implicaciones de seguridad o rendimiento.
  5. Limitación de la pérdida de recursos: desea escribir software que no pierda recursos, pero incluso en lenguajes totalmente gestionados esto es extremadamente difícil en procesos de larga duración, y lo que es peor, es difícil de replicar en un entorno de desarrollo. Una arquitectura multinivel le permite matar y reaparecer los servidores del juego después de cierto tiempo o cantidad de solicitudes para limitar los daños por pérdidas de recursos, sin interrumpir el servicio.
Lie Ryan
fuente
5

Estoy de acuerdo con el monstruo de trinquete. Mientras tengas un solo servidor de juegos, no vale la pena.

Sin embargo, esta arquitectura podría resultar útil cuando necesite escalar horizontalmente. Cuando un servidor de juegos ya no es suficiente y necesita distribuir su juego en varios servidores de juegos por razones de rendimiento, la arquitectura del "servidor de sockets" podría adaptarse fácilmente para convertir el servidor de sockets en un equilibrador de carga que enruta automáticamente las conexiones a uno de los muchos backend servidor.

Pero cuando no está seguro de que alguna vez necesitará esto, es probable que la ingeniería excesiva desarrolle dos aplicaciones de servidor separadas en este momento.

Philipp
fuente
4

Probablemente no lo sea, la mayoría de los idiomas tienen enchufes asincrónicos que le permiten usar múltiples conexiones a la vez sin bloquear mientras los datos están esperando. Esto desplaza la parte del "servidor de sockets" al SO / kernel.

Con un servidor de socket explícito incurrirá en el costo de algunas copias adicionales a medida que pase los datos a través del socket local; Una cosa que matará la escalabilidad son las copias adicionales donde no las necesita.

monstruo de trinquete
fuente
1
A menos que ya sepa que su servidor tendrá requisitos de escalabilidad muy altos, no me preocuparía por el rendimiento en esta etapa. La sobrecarga de copiar algunos datos en la memoria es muy pequeña en comparación con el envío de datos a través de Internet.
Anko