пятница, 15 октября 2010 г.

Game from Scratch: Front of Waterfall

В предыдущей серии мы позанимались словоблудием на тему архитектуры, желания что-нибудь сделать и о том что мы будем использовать. В этой же займемся наконец тем же самым, делом.

В первый раз забросил он невод, и отделил свет от тьмы.
Большие полотна текста плохо способствую пониманию. Поэтому для создания каркаса первого нашего (и позже второго нашего) сервиса полюбуемся на картинку.


Исследуем данное изображение в деталях.

Т.к. наши сервисы живут в событийной среде, им необходимо работать с событиями.
Для этого нам необходимо реализовать некий EventManager. Заниматься он будет обработкой возникших событий и перенаправление их к экземпляром всевозможных Dispatcher'ов.

Т.к. сервис может реализовывать некую свою логику, существует разновидность локального обработчика событий - LocalEventDispatcher. Который никуда, ничего не доставляет, а только исполняет некий свой логический код. В результате которого может породить новое событие и передать его в EventManager своего сервиса. Который вполне вероятно может обратиться к обработчику унаследованному от NetworkEventDispatcher, который в свою очередь это событие отправит сервису, подписавшемуся на него.


Изучив нижнюю часть схемы мы наткнулись на важную вещь - удаленный сервис должен подписываться на события. Однако в случае его недоступности или состояния Offline наш FrontendService должен что-либо отвечать игрокам пытающимся войти в игру. Поэтому в момент когда игрок пытается войти в игру (LoginEvent), локальный обработчик исследует доступность LoginService и генерирует событие о недоступности оного для клиента (LoginServiceIsDown), либо создает событие аутенфикации (AuthenticateEvent), которое отправляется на обработку в NetworkEventDispatcher ответственный за связь с LoginService.

LoginService реализованный с точно такой же структурой проверяет доступно ли ему хранилище аккаунтов (и множество других проверок, например проверяет статус он-лайн игрока) и соответственно генерирует события отказа (AuthenticationFailed) или подтверждения аутенфикации (AuthenticationCompleate), детализируя их кодом ошибки или идентификатором сессии.

Следующим шагом для клиента будет отправить событие на вход в игру (TryToOnline), после чего логин сервис поставит флаг о том, что игрок онлайн и сообщит об этом LoginService. А тот генерирует событие, которое принудит остальные игровые сервисы (Сервис сумок, позиции на карте, умений и заклинаний etc) получить данные из хранилищ.

Да, вогонечности чуткой души поэта, которая посредством  самой  структуры  стиха  сублимирует одно, освобождается от другого и  находит  общий  язык  с  фундаментальной дихотомией третьего. Приходит глубокое и ясное  понимание  того...  э-э... того... Того, о чем шла речь в произведении!

Остается вопрос зачем же все так сложно. Для чего нужны события etc, если это можно сделать в одном сервисе и забыть навсегда.

А дело в трех вещах.

1. Масштабирование;
2. Гибкость;
3. Ощущение собственной охуенности.

Самый важный пункт на самом деле гибкость. Так например у каждого сервиса может существовать своя собственная база данных.

Например для LoginService можно использовать MySQL или PostgreSQL. И оттуда же будут брать данные всякие форумы, панели для работы с пользователями и что угодно другое.

А сервис ответственный за сумку игрока будет работать с какой-нибудь key-value  NoSQL базой данных. Переодически сбрасывая туда изменения произошедшие с сумкой и экипировкой персонажа. Ему ведь не важна реляционная модель.

При этом сревис ответственный за позициионирование игрока будет брать данные из-той же NoSQL базы. А сервис ответственный за реализацию гильдий обратиться в SQL базу, дабы на сайте можно было отображать списки гильдий.

Можно не мудрствуя лукаво наоборот все хранить в MySQL и наслаждаться жизнью.

Чем больше вариаций вы изначально закладываете в архитектуру и чем больше распределяете нагрузку между серверами, процессами и мини-приложениями тем больше вероятность, что в последствии вы справитесь с возрастающими нагрузками. Хотя это редко бывает важно на стадии создания прототипа, в дальнейшем это может оказаться критическим.

В следующем этапе мы займемся созданием FrontendServce, реализуем LocalDispatchManager и реализуем несколько событий - LoginEvent, TryToLogin, LoginServiseIsDown и напишем маленький скрипт эмулирующий клиент, для тестирования этого добра.

Комментариев нет:

Отправить комментарий