Sistemas multiagente en la construcción de espacios virtuales.

Uno de los problemas críticos que surgen al construir sistemas multiusuario es el escalado. Existen varias soluciones a estos problemas: fragmentación, modelo de servicio, sistema de entidad-componente. Hoy consideraremos todas las opciones y también discutiremos un caso práctico para resolver el problema. Únete ahora!



Parte 1
Parte 2

Paso la palabra a los autores.

Enfoques tradicionales para construir sistemas multiusuario. Arquitectura de servicio


Históricamente, el primer método para resolver el problema del escalado fue la fragmentación: dividir todo el sistema en varios servidores por cualquier criterio sin un estado general del mundo. Es decir, hasta cierto número de usuarios, podrían estar en el mismo servidor, verse e interactuar entre ellos; pero al agregar nuevos, terminaron en copias del espacio virtual que se ejecuta en otro servidor y, en consecuencia, no pudieron interactuar con otros. Está claro que esto no es una solución al problema, es una solución alternativa. Y aunque el fragmentación tiene sentido incluso ahora, en muchos casos se requieren enfoques que realmente puedan aumentar la posible carga en el servidor.

La segunda técnica común es el modelo de servicio. El servidor tiene una serie de componentes que se pueden duplicar fácilmente. Por ejemplo, esta es una base de datos y está trabajando con ella, o un servidor de activos que los envía a un cliente, o un servidor de autorización. Todos estos servicios se distinguen por el hecho de que puede tenerlos en varias instancias y paralelizar las solicitudes para ellos.

El principal problema es el estado compartido


Pero el problema principal es diferente. ¿Qué hacer con un estado específico del mundo, el estado del espacio virtual? Supongamos que nuestro "mundo" consiste en una escena 3D, un conjunto de objetos y varios usuarios conectados. Teóricamente, podemos duplicar algunos componentes de software que son responsables de trabajar con la escena en el lado del servidor. Pero el problema es que el estado de la escena es una cosa común a todos estos componentes. Por consiguiente, al paralelizar los manejadores, necesitamos resolver de alguna manera el problema de sincronizar el trabajo con los datos, y al mismo tiempo en la sincronización misma podemos perder más rendimiento que ganar en paralelismo.

Solución: Sistema de entidad-componente. Problemas en el caso del Lejano Oriente


Uno de los enfoques relativamente recientes para tales problemas es ECS (Entity - Component System). En esta versión, representamos el objeto del sistema como una determinada entidad que tiene algunas propiedades. Por ejemplo, esta puede ser la posición de un objeto en el espacio y su velocidad. Además, todo lo que almacenamos en el objeto en sí es solo algunos datos, pero no la lógica de trabajar con ellos. Es decir, en nuestro caso, simplemente se asignarán seis números al objeto: el vector de coordenadas y el vector de velocidad.

La segunda parte de ECS es trabajador, un sistema que funciona con un tipo específico de componente. Por ejemplo, en nuestro caso, puede ser un sistema que cambia las coordenadas de un objeto cada segundo, añadiéndoles velocidad. La idea principal es que el trabajador no sabe nada sobre el objeto como tal, solo tiene una cola, una tubería de componentes que debe procesar de acuerdo con ciertas reglas. En consecuencia, podemos paralelizar a los trabajadores, así como los servicios paralelizados.

Sistemas de agentes como método para escribir código paralelo


El enfoque de múltiples agentes tampoco es una novedad especial, pero recientemente, el interés en los sistemas de agentes ha ido creciendo. Hay una serie de artículos bastante buenos que lo cuentan en detalle, por lo que aquí enumeramos brevemente solo los principios más generales de dichos sistemas:

  1. El componente principal del sistema es un componente llamado agente o actor. De alguna manera, se parece a un objeto familiar para todos, pero el actor no tiene métodos públicos, la única forma de comunicarse con él es enviarle un mensaje;
  2. Para enviar un mensaje al agente existe el concepto de "enlaces". El enlace proporciona una interfaz determinada (en varias implementaciones puede verse muy diferente), lo que le permite enviar mensajes. Una de las propiedades importantes aquí es la transparencia de ubicación y la presencia de cada agente con una dirección, una cadena que le permite obtener un enlace al agente independientemente de su ubicación física, es decir. el agente puede ubicarse y trabajar en el sistema del agente en la misma computadora, o tal vez en otra; en este caso, el enlace se obtiene en alguna dirección de red;
  3. El agente tiene una cola de mensajes y se procesan secuencialmente. Un agente puede ser una máquina de estados que cambia estados y manejadores de mensajes en el orden de reacción a ellos;
  4. Como regla general, los sistemas multiagente son jerárquicos, es decir, los agentes forman una especie de árbol. En este caso, un error en uno de los agentes no detiene todo el sistema, solo un agente específico se desconecta y envía un mensaje de error a su antecesor. Uno de los enfoques populares para manejar tales errores es dejar que se bloquee: cuando un agente falla, simplemente creamos una nueva copia del mismo;
  5. Crear un nuevo agente no es una operación que requiere muchos recursos, y crear el sistema en sí es muy costoso.

Muy a menudo, los sistemas de agentes se usan solo en el enfoque que usa ECS. Dado que el sistema de agentes hace que sea muy fácil crear la cantidad requerida de trabajadores y hacer que su trabajo sea paralelo, simplemente distribuyendo el flujo de mensajes entre ellos, este parece un enfoque muy prometedor. Por ejemplo, así es como funciona SpatialOS de Improbable.

Los problemas surgen aquí en un plano ligeramente diferente. El enfoque de ECS es bastante simple, pero en principio no puede llamarse intuitivo, especialmente para programadores inexpertos. Por lo tanto, la creación de código de usuario en dicho sistema es una tarea bastante trivial. Además, surgen preguntas sobre la portabilidad de varios objetos entre instancias de servidores virtuales, porque junto con el objeto debemos transferir a todos los trabajadores si ellos (para este tipo de componente) no están presentes en otro servidor. En principio, algunas implementaciones de sistemas de agentes pueden resolver algunos de estos problemas, pero hemos elegido un enfoque diferente.

Nuestro caso es la esencia del Lejano Oriente como agente


En nuestro caso, cada objeto espacial virtual es un agente, o más bien, un sistema de agentes. Comparando con el ECS clásico, podemos decir que cada entidad en nosotros lleva un sistema de "micro trabajadores", ligados al objeto mismo. Al mismo tiempo, se conservan todas las ventajas del sistema de agente (es decir, podemos ejecutar dicho objeto en un hilo separado, en una máquina separada, etc., simplemente cambiando la configuración del servidor), pero el objeto sigue siendo portátil y escribir scripts para él no requiere división ECS .

En este caso, el estado del mundo se divide en el estado de los objetos individuales, y cada uno de ellos puede procesarse por separado. En el cliente, también creamos un sistema de agente, que es una especie de reflejo del estado del servidor, y asociamos cada agente de cliente con el agente del servidor. Entre otras cosas, esto también aumenta la confiabilidad del sistema, ya que si un objeto individual falla, solo este objeto está deshabilitado, y no todo el espacio virtual.
En un poco más de detalle, se ve así:



Cualquier objeto espacial es un sistema de agente pequeño que consiste en el agente principal de la entidad que se crea cuando se inicia el servidor, que no es un agente contenedor de componentes y un conjunto de componentes de controlador de mensajes. Para conectar al cliente, se utiliza la propiedad de transparencia de red, es decir, cada objeto específico en el cliente tiene un enlace al objeto del agente del servidor. Al mismo tiempo, cuando se conecta, se crea dinámicamente un nuevo agente, que es un descendiente del principal.



También se crea un sistema de agente en el lado del cliente, pero los agentes de entidad en él están formados por un mensaje del lado del servidor. Después de la creación, el agente recibe un enlace al agente del servidor y crea un componente de procesamiento de mensajes que incluye colas para recibir y enviar mensajes desde el servidor. También se crea un objeto Unity, y las partes cliente de los componentes del objeto se heredan de MonoBehaviour. Al mismo tiempo, la parte de Unity y la parte de agente trabajan en diferentes subprocesos, el controlador de mensajes es responsable de la sincronización (si es posible, se minimiza).

Algo como esto (sin detalles especiales) se parece a la implementación del espacio virtual dinámico en la variante JIF. En el próximo artículo, le informaremos sobre big data personal y trabajaremos con estadísticas, así como sobre blockchain.

Los autores


Jedium es una empresa asociada de Microsoft que trabaja en el campo de la realidad virtual aumentada y la inteligencia artificial. Jedium ha desarrollado un marco para simplificar el desarrollo de proyectos complejos en Unity, parte del cual está disponible públicamente en GitHub . Jedium planea reponer el repositorio con nuevos módulos de marco, así como soluciones de integración con Microsoft Azure.

Vitaliy Chashchin : desarrollador de software con más de 10 años de experiencia en el diseño e implementación de aplicaciones tridimensionales cliente-servidor, desde el concepto hasta la implementación e integración completas de aplicaciones y soluciones en el campo de la realidad virtual. Arquitecto de sistemas Jedium LLC, MSc en TI.

Alexey Sarafanov

Gerente de Marketing en Jedium LLC.

Sergey Kudryavtsev

CEO y fundador de Jedium LLC.

Source: https://habr.com/ru/post/es419129/


All Articles