Разработка высоконагруженного игрового сервера. Сетевая часть.

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

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

Вспомним концепцию классического сокет-сервера. На серверной стороне создается один поток для приема входящих соединений. Далее, при подключении каждого нового клиента, для него создается еще два потока – один для обработки входящих данных, другой – реализующий очередь пакетов для отправки юзеру. В итоге, например, 1000 онлайн означает минимум 2000 запущенных тредов, это при том, что даже современные процессоры позволяют одновременно работать максимум 16-32 тредам. Выходит, серверный процессор начинает испытывать перегрузки, сервер начинает упираться в количество одновременно открытых файлов, память начинает выедаться катастрофически. В общем, проблем куча. Ни о каких 20-30К онлайна тут речи вообще нет.

Как вы уже поняли, основная проблема – количество запущенных потоков. Откуда возникает задача – уменьшить это количество. Стандартный сокет нам этого не позволяет, но здесь на помощь приходят асинхронные сокеты и концепция асинхронного программирования. Суть концепции – событие инициируется сейчас, но реакция на него поступит не сразу же, а “когда-нибудь потом”. Звучит странно, но мы попробуем это расшифровать. :)

Для начала – сделаем правильные сокеты. В сети существует чудесное (дай бог здоровья его создателям) решение – Netty (Netty Project). Эта библиотека для Java реализует великое множество сетевых инструментов – http, ssl, сокеты, и разные их комбинации. Документация написана мутновато, да и сам факт того, что библиотека имеет массу возможностей, разобраться в этом всем и выделить для себя то, что нужно – ой как не просто. Мы прошли этот путь и спешим поделиться результатами. в свое время нам очень не хватало подобной статьи. :)

Основная суть – создается поток-обработчик входящих соединений, и ограниченное число (по умолчанию 8 ) тредов, принимающих входящие пакеты. Очередной принятый пакет отправляется на обработку игровой логике сервера, сервер формирует ответ, и отправляет в канал нужного клиента. Все просто! :) Трудность тут одна – тредов-приемников всего 8(пусть даже 32, 64), а клиентов в сотни раз больше. Поэтому обрабатывать входящие пакеты внутри приемника никак нельзя. Там вообще категорически нельзя выполнять никакие блокирующие действия. Решение очевидно: приняли пакет, породили еще один поток, который займется обработкой и вуаля, готовы принимать следующий пакет. Никто никого не ждет, все летает. Поток-обработчик уже без всяких изысков направляет данные куда надо, данные обрабатываются игровой логикой, результат обработки отсылается клиенту, поток тут же умирает, освобождая ресурсы.

Казалось бы, мы тут плодим по треду на каждый входящий пакет – не многовато ли будет? Мы тоже этого опасались, но тесты и последующая практическая реализация показали следующие результаты: на 4-х ядерном процессоре (по 2 треда на ядро) при онлайне 5К в любой момент времени на сервере запущено в среднем (всего!!!) 30-40 тредов. Конечно, сама игровая логика там тоже оптимизирована, и от одного клиента поступает не больше одного запроса в 10 секунд, но запас мощности там еще колоссальный, ни по каким параметрам ни в какие полки не упремся еще долго. Кластер из 3-х серверов, построенный на этой сетевой реализации успешно и не особо напрягаясь держал в пике до 25К онлайна и по оценкам мог держать в 2 раза больше. А 25 тысяч онлайн – это очень серьезная цифра, это успех приложения! :)

Хотите так же? :) К сожалению, в этой статье привести исходный код не успеваем, но следующая статья будет посвящена именно этому, и только этому. Мы не будем долго тянуть с ее выпуском, она выйдет буквально через пару дней. Следите за обновлениями! :) Ждем ваших вопросов и пожеланий.

Эта запись была опубликована в рубрике Мысли о разработке и отмечена метками , , , , , . Добавить в закладки ссылку.

Комментирование закрыто.