- PVSM.RU - https://www.pvsm.ru -
Одна из критических проблем, которые возникают при построении многопользовательских систем – масштабирование. Существуют различные варианты решения это проблемы: шардинг, сервисная модель, Entity-Component System. Сегодня рассмотрим все варианты, а также обсудим практический кейс решения вопроса. Присоединяйтесь!
Передаю слово авторам.
Исторически первым методом решения проблемы масштабирования был шардинг – разделение всей системы на ряд серверов по какому-либо признаку без общего состояния мира. То есть, до определенного количества пользователей они могли находиться на одном сервере, видеть друг друга и взаимодействовать друг с другом; но при добавлении новых оказывались в копии виртуального пространства, работающей на другом сервере, и, соответственно, не могли взаимодействовать с другими. Понятно, что это не решение проблемы, это ее обход. И хотя шардинг вполне имеет смысл и сейчас, во многих случаях требуются подходы, позволяющие реально увеличить возможную нагрузку на сервер.
Второй общепринятой техникой является сервисная модель. У сервера есть ряд компонентов, которые достаточно легко могут быть продублированы. Например, это база данных и работа с ней, или сервер ассетов, который пересылает их на клиент, или сервер авторизации. Все эти сервисы отличаются тем, что их можно иметь в нескольких экземплярах, и распараллеливать запросы на них.
Но основная проблема заключается в другом. Что делать с конкретным состоянием мира, состоянием виртуального пространства? Предположим, наш “мир” состоит из одной 3D — сцены, набора объектов на ней и нескольких подключенных пользователей. Теоретически мы можем дублировать какие-то программные компоненты, которые отвечают за работу со сценой на стороне сервера. Но проблема в том, что состояние сцены — одно, общее для всех этих компонентов. Соответственно, при распараллеливании обработчиков нам нужно как-то решать проблему синхронизации работы с данными, и при этом на самой синхронизации мы можем проиграть в производительности больше, чем выиграть на параллельности.
Один из относительно недавно возникших подходов к таким проблемам — это ECS (Entity — Component System). В этом варианте мы представляем объект системы как некую сущность, обладающую некоторыми свойствами. Например, это может быть положение объекта в пространстве и его скорость. При этом все, что мы храним на самом объекте – это только некоторые данные, но не логика работы с ними. То есть в нашем случае к объекту просто будут приписаны шесть чисел — вектор координат и вектор скорости.
Вторая часть ECS — это worker, система, которая работает с конкретным типом компонентов. Например, в нашем случае это может быть система, которая каждую секунду меняет координаты объекта, прибавляя к ним скорость. Основная идея в том, что worker ничего не знает об объекте как таковом – у него есть просто очередь, конвейер компонентов, которые он должен обработать по определенным правилам. Соответственно, мы можем распараллелить worker’ов, так же, как распараллеливали сервисы.
Мультиагентный подход — тоже не особая новинка, но в последнее время интерес к агентным системам растет. Есть ряд достаточно хороших статей, рассказывающих о нем в деталях, поэтому тут мы кратко перечислим только самые общие принципы таких систем:
Достаточно часто агентные системы используются как раз в подходе с использованием ECS. Так как агентная система позволяет очень легко создавать необходимое количество worker’ов и распараллеливать их работу, просто распределяя между ними поток сообщений, то это выглядит весьма перспективным подходом. Например, так устроена SpatialOS от Improbable.
Проблемы здесь возникают в несколько другой плоскости. Подход ECS достаточно прост, но в принципе его нельзя назвать интуитивно понятным, особенно для неопытных программистов. Поэтому создание пользовательского кода в такой системе представляет собой достаточно нетривиальную задачу. Также возникают вопросы с переносимостью различных объектов между экземплярами серверов виртуального пространства, потому что вместе с объектом мы должны перенести всех worker’ов, если они (под такой тип компонента) не присутствуют на другом сервере. В принципе, некоторые реализации агентных систем позволяют решить часть подобных проблем, но мы выбрали другой подход.
В нашем случае каждый объект виртуального пространства представляет собой агент, а точнее, систему агентов. Сравнивая с классическим ECS, можно сказать, что у нас каждая сущность несет в себе систему “микро-worker’ов”, привязанную к самому объекту. При этом сохраняются все преимущества агентной системы (то есть, мы можем запускать такой объект в отдельном потоке, на отдельной машине и т.д., просто изменяя настройки сервера), но объект остается переносимым, а написание для него скриптов не требует ECS-деления.
В этом случае состояние мира дробится на состояние отдельных объектов, и каждый из них может обрабатываться отдельно. На клиенте мы также строим агентную систему, являющуюся своего рода отражением состояния сервера, и связываем каждый агент клиента с агентом сервера. Кроме всего прочего, это повышает и надежность системы, так как при ошибке отдельного объекта отключается только этот объект, а не все виртуальное пространство.
Немного более в деталях это выглядит так:
Любой объект пространства представляет собой небольшую агентную систему, состоящую из основного агента сущности, который создается при запуске сервера, не являющегося агентом контейнера компонент и набора компонент-обработчиков сообщений. Для подключения клиента используется свойство сетевой прозрачности, то есть у каждого конкретного объекта на клиенте есть ссылка на серверный агент-объект. При этом при подключении динамически создается новый агент, являющийся потомком основного.
На стороне клиента также создается агентная система, но агенты сущностей в ней образуются по сообщению со стороны сервера. После создания, агент получает ссылку на серверный агент и создает компонент обработки сообщений, включающий в себя очереди на прием и отсылку сообщений с сервера. Также создается объект Unity, и клиентские части компонентов объекта, унаследованные от MonoBehaviour. При этом Unity-часть и агентная часть работают в разных потоках, за синхронизацию отвечает обработчик сообщений (по возможности она сводится к минимуму).
Примерно так (без особых подробностей) выглядит реализация динамического виртуального пространства в варианте JIF. В следующей статье мы вам расскажем про персональные большие данные и работу со статистикой, а также про блокчейн.
Компания Jedium [3]— партнерская компания Microsoft, работающая в сфере виртуальной, дополненной реальности и искусственного интеллекта. Jedium разработала фреймворк для упрощения разработки комплексных проектов на Unity, часть которого находится в открытом доступе на GitHub [4]. Jedium планирует пополнять репозиторий новыми модулями фреймворка, а также интеграционными решениями с Microsoft Azure.
Виталий Чащин — Разработчик программного обеспечения с более чем 10 годами опыта в дизайне и реализации трехмерных клиент-серверных приложений – от концепции до полной реализации и интеграции приложений и решений в области виртуальной реальности. Системный архитектор Jedium LLC, MSc in IT.
Алексей Сарафанов
менеджер по маркетингу в Jedium LLC.
Сергей Кудрявцев
CEO and founder of Jedium LLC.
Автор: sahsAGU
Источник [5]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/microsoft/288139
Ссылки в тексте:
[1] Часть 1.: https://habr.com/company/microsoft/blog/416343/
[2] Часть 2.: https://habr.com/company/microsoft/blog/418111/
[3] Jedium : https://jedium.com
[4] на GitHub: https://github.com/Jedium
[5] Источник: https://habr.com/post/419129/?utm_campaign=419129
Нажмите здесь для печати.