Последние два года я занимаюсь разработкой сервера игр на платформе RedDwarf – свободной (GPLv2) серверной платформе для создания онлайн-игр на Java. На Хабре очень мало информации об этой платформе, поэтому я решил исправить этот недостаток.
Разработка данного движка изначально велась компанией Sun, сама платформа называлась Sun Game Server (аббревиатура sgs до сих пор используется в наименованиях пакетов). В 2005 году сервер был представлен миру под названием Project Darkstar. После того, как Oracle купила Sun, от поддержки проекта сановцы отказались, платформа была переименована в RedDwarf Server и сейчас существует только при поддержке сообщества. Проект развивается сейчас гораздо медленней, но всё же развивается – в прошлом году вышла версия 0.10.2. Всех планируемых фишек (прозрачного масштабирования) в ней ещё нет, но как основа для игрового сервера используется во многих проектах.
Игровой сервер на платформе RedDwarf состоит из следующих частей.
Внутренняя база данных – это высокопроизводительная встраиваемая база данных (используется BerkleyDB), которая используется для хранения служебных и игровых данных в процессе игры. В этой БД хранятся все игровые объекты, игровые и внутренние задачи и события. Именно с помощью БД реализована транзакционность выполнения задач. Это позволяет запускать его с того же места, где он был остановлен: игра продолжится как ни в чем не бывало.
Ядро RedDwarf включает в себя все заботы о работе с базой данных BerkleyDB, с сетью, подключением-отключением пользователей, планированием отложенных и периодических задач.
Расширения представляют собой легко подключаемые плагины, которые дают возможность использовать функциональность, не включенную в ядро. Существуют расширения для профилирования, работой с внешней БД (SQL), работы с HTTP-сервисами.
Игровое приложение пишется разработчиками игры на языке Java. Игровое приложение использует API, предоставляемое ядром и расширениями. RedDwarf накладывает некоторые ограничения на игровое приложение: задачи должны быть короткими, не производить ввод-вывод напрямую, не создавать свои потоки, а пользоваться механизмом задач.
Любое игровое (либо внутреннее) событие – это задача. Задачи сериализуются, записываются в БД, после чего по возможности считываются и выполняются. В начале выполнения каждой задачи открывается транзакция внутренней базы данных, после завершения задачи происходит коммит транзакции. Если во время выполнения задачи произошло необработанное исключение, либо задача выполнялась больше 100мс (по умолчанию), транзакция откатывается.
В связи с этим ещё один интересный момент: если имеет место конфликт транзакций (то есть один и тот же игровой объект был изменен параллельно в разных задачах) – то транзакция откатывается и задача выполняется ещё раз. Благодаря этому программа пишется как однопоточная – даже использование synchronized и блокирующих коллекций запрещено (они могут привести к дедлокам).
Хранение задач в базе данных дает уникальные возможности.
Первое – это возможность безболезненно возобновлять работу сервера после его остановки или падения. Правда, на практике бывали случаи, когда падение сервера было вызвано лавинообразным размножением задач (из-за ошибки в коде) – и тогда для восстановления работы сервера приходилось либо много шаманить, либо удалять всю базу данных.
Вторая уникальная возможность заключается в создании прозрачного масштабирования – сериализованные задачи легко передаются между отдельными нодами кластера серверов, и выполняются там, где есть возможность. К сожалению, это масштабирование ещё не реализовано до конца и на практике применяться пока не может.
В платформе реализован удобный шедулер, позволяющий планировать единоразовые, отложенные и периодические задачи и отменять их.
Есть возможность наблюдения за состоянием сервера и администрирования с помощью JMX.
Для того чтобы обеспечить транзакционность и позволить программистам (почти) не задумываться о многопоточности все игровые объекты должны реализовывать интерфейс ManagedObject. Работа с такими объектами может вестись только в рамках транзакций (то есть нельзя просто запустить свой отдельный поток и в нем работать с такими объектами). Ссылка на такой объект должна храниться не в явном виде, а внутри специального объекта – ManagedReference. Необходимость разыменовывать такие ссылки слегка раздражает, но помня о том, что это избавляет от возни с блокировками, быстро привыкаешь.
Замечательная возможность, даруемая разработчикам игр под Reddwarf – это каналы для сообщений. Канал может иметь большое количество подписчиков и при публикации сообщения в канал оно доставляется всем адресатам. Реализация каналов такова, что этот механизм работает значительно быстрее нежели обход всех подписчиков в цикле и отсылка сообщения каждому из них.
Для RedDwarf существует множество библиотек для написания клиентской части на различных языках программирования. Разработчиками платформы поддерживаются клиентские библиотеки на Java и С. Также имеются библиотеки для ActionScript, Objective-C, C#, Python.
Поскольку многое уже реализовано в самой платформе, для получения игры программистам необходимо сделать следующее:
В качестве итога можно сказать, что Reddwarf представляет собой неплохую платформу для разработки серверов онлайн-игр: освобождает программиста от забот о многопоточности, предоставляет удобное API для работы с внутренней базой данных, с задачами и сетью.
В статье на хабре я написал как сделать свое первое приложение под RedDwarf.
Официальный сайт проекта
FAQ по Reddwarf
Презентация с описанием архитектуры
Если вы ведёте свой блог, микроблог, либо участвуете в какой-то популярной социальной сети, то вы можете быстро поделиться данной заметкой со своими друзьями и посетителями. Для этого воспользуйтесь предлагаемыми ниже кнопками:
Блог: http://romanlovetext.blogspot.com/
История
Разработка данного движка изначально велась компанией Sun, сама платформа называлась Sun Game Server (аббревиатура sgs до сих пор используется в наименованиях пакетов). В 2005 году сервер был представлен миру под названием Project Darkstar. После того, как Oracle купила Sun, от поддержки проекта сановцы отказались, платформа была переименована в RedDwarf Server и сейчас существует только при поддержке сообщества. Проект развивается сейчас гораздо медленней, но всё же развивается – в прошлом году вышла версия 0.10.2. Всех планируемых фишек (прозрачного масштабирования) в ней ещё нет, но как основа для игрового сервера используется во многих проектах.
Основные принципы
Игровой сервер на платформе RedDwarf состоит из следующих частей.
- Игровое приложение
- Расширения
- Ядро
- Внутренняя БД
Внутренняя база данных – это высокопроизводительная встраиваемая база данных (используется BerkleyDB), которая используется для хранения служебных и игровых данных в процессе игры. В этой БД хранятся все игровые объекты, игровые и внутренние задачи и события. Именно с помощью БД реализована транзакционность выполнения задач. Это позволяет запускать его с того же места, где он был остановлен: игра продолжится как ни в чем не бывало.
Ядро RedDwarf включает в себя все заботы о работе с базой данных BerkleyDB, с сетью, подключением-отключением пользователей, планированием отложенных и периодических задач.
Расширения представляют собой легко подключаемые плагины, которые дают возможность использовать функциональность, не включенную в ядро. Существуют расширения для профилирования, работой с внешней БД (SQL), работы с HTTP-сервисами.
Игровое приложение пишется разработчиками игры на языке Java. Игровое приложение использует API, предоставляемое ядром и расширениями. RedDwarf накладывает некоторые ограничения на игровое приложение: задачи должны быть короткими, не производить ввод-вывод напрямую, не создавать свои потоки, а пользоваться механизмом задач.
Задачи
Любое игровое (либо внутреннее) событие – это задача. Задачи сериализуются, записываются в БД, после чего по возможности считываются и выполняются. В начале выполнения каждой задачи открывается транзакция внутренней базы данных, после завершения задачи происходит коммит транзакции. Если во время выполнения задачи произошло необработанное исключение, либо задача выполнялась больше 100мс (по умолчанию), транзакция откатывается.
В связи с этим ещё один интересный момент: если имеет место конфликт транзакций (то есть один и тот же игровой объект был изменен параллельно в разных задачах) – то транзакция откатывается и задача выполняется ещё раз. Благодаря этому программа пишется как однопоточная – даже использование synchronized и блокирующих коллекций запрещено (они могут привести к дедлокам).
Хранение задач в базе данных дает уникальные возможности.
Первое – это возможность безболезненно возобновлять работу сервера после его остановки или падения. Правда, на практике бывали случаи, когда падение сервера было вызвано лавинообразным размножением задач (из-за ошибки в коде) – и тогда для восстановления работы сервера приходилось либо много шаманить, либо удалять всю базу данных.
Вторая уникальная возможность заключается в создании прозрачного масштабирования – сериализованные задачи легко передаются между отдельными нодами кластера серверов, и выполняются там, где есть возможность. К сожалению, это масштабирование ещё не реализовано до конца и на практике применяться пока не может.
В платформе реализован удобный шедулер, позволяющий планировать единоразовые, отложенные и периодические задачи и отменять их.
Есть возможность наблюдения за состоянием сервера и администрирования с помощью JMX.
Managed Objects
Для того чтобы обеспечить транзакционность и позволить программистам (почти) не задумываться о многопоточности все игровые объекты должны реализовывать интерфейс ManagedObject. Работа с такими объектами может вестись только в рамках транзакций (то есть нельзя просто запустить свой отдельный поток и в нем работать с такими объектами). Ссылка на такой объект должна храниться не в явном виде, а внутри специального объекта – ManagedReference. Необходимость разыменовывать такие ссылки слегка раздражает, но помня о том, что это избавляет от возни с блокировками, быстро привыкаешь.
Каналы для массовой доставки сообщений
Замечательная возможность, даруемая разработчикам игр под Reddwarf – это каналы для сообщений. Канал может иметь большое количество подписчиков и при публикации сообщения в канал оно доставляется всем адресатам. Реализация каналов такова, что этот механизм работает значительно быстрее нежели обход всех подписчиков в цикле и отсылка сообщения каждому из них.
Клиентская часть
Для RedDwarf существует множество библиотек для написания клиентской части на различных языках программирования. Разработчиками платформы поддерживаются клиентские библиотеки на Java и С. Также имеются библиотеки для ActionScript, Objective-C, C#, Python.
Что требуется от разработчика игры
Поскольку многое уже реализовано в самой платформе, для получения игры программистам необходимо сделать следующее:
- Создать игровые сущности и связи между ними.
- Реализовать хранение игровых данных (либо во встроенной БД, либо с помощью расширений — во внешней).
- Разработать протокол общения сервера и клиента (в самом RedDwarf для этого инструментов почти нет).
- Запрограммировать игровую логику, реакцию сервера на действия клиента.
Заключение
В качестве итога можно сказать, что Reddwarf представляет собой неплохую платформу для разработки серверов онлайн-игр: освобождает программиста от забот о многопоточности, предоставляет удобное API для работы с внутренней базой данных, с задачами и сетью.
В статье на хабре я написал как сделать свое первое приложение под RedDwarf.
Литература
Официальный сайт проекта
FAQ по Reddwarf
Презентация с описанием архитектуры
Если вы ведёте свой блог, микроблог, либо участвуете в какой-то популярной социальной сети, то вы можете быстро поделиться данной заметкой со своими друзьями и посетителями. Для этого воспользуйтесь предлагаемыми ниже кнопками:
Блог: http://romanlovetext.blogspot.com/