Масштабируемость многопользовательского игрового сервера Java - PullRequest
10 голосов
/ 11 сентября 2011

Я создал многопользовательскую онлайн-игру для Android под названием The Infinite Black: https://market.android.com/details?id=theinfiniteblack.client

По своей наивности я ожидал умеренного темпа роста, равного примерно 1000 игроков в месяц, и мне нужно было управлять ~20 активных топов клиентов TCP / IP.

Игра имеет неожиданно взрывной рост с более чем 40 000 новых пользователей в неделю, в среднем ~ 300 активных соединений одновременно и растет в геометрической прогрессии.

Архитектура сервера состоит из 2 потоков на соединение (блокирует чтение / запись), один поток ServerSocket для порождения новых клиентов и один поток контроллера, который опрашивает каждого клиента на предмет новых действий, применяет его к игровому миру, а затем сбрасывает данные, когдаготово.

Сервер построен на Java, в котором я не очень хорошо разбираюсь, особенно в такой стрессовой ситуации, как эта.C # действительно испортил меня, когда дело доходит до управления памятью и потоками.

Чтобы подойти к делу ... Я только что заказал две очень мощные системы, которые будут работать как выделенные игровые серверы и хотят максимально использовать ресурсы.Большая часть информации о конфигурации ресурсов Java оказалась обманчивой, неправильной или устаревшей.

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

Новые серверы имеют 16 ГБ ОЗУ и процессоры i7-2600K Sandy Bridge 3,4 ГГц: какие параметры доступны в конфигурации, чтобы максимально использовать это преимущество?Моя цель - 1200 онлайн-клиентов одновременно на сервер (2400 потоков).

Какие неожиданные ловушки и проблемы мне следует беспокоить?

Я прочитал дико противоречивые истории в максимальном потокеимеет значение: развалится ли я, если я попытаюсь протолкнуть 2400 активных потоков?

Кажется, что Java не предназначена для задач такого типа.Стоит ли подумать о переносе сервера на другой язык?

В настоящее время я запускаю сервер в режиме отладки вне Eclipse, пока он находится в разработке (тьфу ..)

Это моя конфигурация Eclipse .ini:

- launcher.XXMaxPermSize 256M

-Xms256m

-Xmx1024m

Ответы [ 3 ]

8 голосов
/ 11 сентября 2011

Вы не дали понять, откуда возникло ваше сомнение.

Plurk Comet: обработка 100 000+ параллельных соединений с Netty (2009)

В 1999 году я развернул веб-сервер Java, который обрабатывал 40000 запросов поиска желтых страниц в час (на серверах было 400 МГц ЦП), а в 2004 году я разработал приложение Java, которое обрабатывало 8000 одновременных подключений на сервер (на двойной частоте 1,2 ГГц Sparc). серверы) Было шесть серверов шлюзов и один главный сервер для управления ими и централизации событий.

Вероятно, ваш профиль будет другим, но я могу сказать, что Java поддерживала большие объемы веб-серверов до выпуска C #.

Лично у меня не было бы более 10 000 одновременных подключений на сервер, но это практическое правило, которое может больше не выполняться. Вы можете иметь 32 000 потоков в одной JVM. В Linux это не намного больше. Однако для минимизации времени полного сбора мусора на одном сервере необходимо иметь несколько шлюзов JVM (лучший способ минимизировать время полного сбора мусора - это избавиться от меньшего количества мусора, но для этого может потребоваться больше усилий)

Новые серверы имеют 16 ГБ ОЗУ и процессоры i7-2600K Sandy Bridge 3,4 ГГц: какие параметры доступны в конфигурации, чтобы максимально использовать это преимущество? Моя цель - 1200 онлайн-клиентов сразу на сервер (2400 потоков).

Я не могу себе представить, почему это будет проблемой.

С какими неожиданными подводными камнями и проблемами я должен быть связан?

Считая, что вам нужно включить все возможные параметры командной строки, когда есть вероятность, что вы можете убрать их все. Если у вас есть 4 шлюза JVM с 300 подключениями каждый, это может использовать всю память, и вам даже не нужно будет указывать параметр -Xmx.

Кажется, что Java не предназначена для задач такого типа. Стоит ли подумать о переносе сервера на другой язык?

Вам лучше спросить себя, почему вы в это верите. У вас есть проблема, которую нужно решить, или сомнение, которое может быть или не быть необоснованным.

Это моя конфигурация Eclipse .ini:

То, как вы настраиваете eclipse, не запрещает устанавливать любую программу, запускаемую из eclipse.

BufferedOutputStream подходит для большинства приложений и может работать до 1000 соединений в JVM. Однако Java 1.4 (2002) добавила NIO, который является более легким для масштабирования вашей системы до 10 000 подключений и более.

Кстати: сервер, который я разработал в 2003 году, был основан на диспетчере NIO, но он довольно сложный, если вы не используете стандартную библиотеку, такую ​​как Netty.

С тех пор я использую один поток для каждой модели подключения для успешной блокировки NIO. Я считаю, что это проще в управлении, чем при использовании диспетчера, и может иметь более низкие характеристики задержки. У меня есть поток монитора, который периодически проверяет соединения, не блокирующие записи, и закрывает их, если они есть. Я не верю, что вам нужно два потока на соединение, но я не верю, что это изменит вашу ситуацию, потому что у вас не будет достаточно соединений на сервер, чтобы иметь значение.

Как подсвечивает кодер, рассматривали ли вы возможность использования UDP для менее важной широковещательной информации?

4 голосов
/ 11 сентября 2011

В Java каждый поток занимает столько же памяти в стеке, что и любой другой поток. Это означает, что ваш основной поток, скажем, имеет зарезервированный размер 32 КБ (который, я думаю, используется по умолчанию), будет иметь тот же зарезервированный размер, что и ваши потоки связи (который, вероятно, только 1 КБ, если вы об этом думаете!). Именно поэтому Java придумал nio - так что вам не нужен поток для соединения.

Давайте приведем пример 1 г оперативной памяти. С 32 КБ на поток, предполагая, что у нас есть половина нашей памяти для стека и половина для кучи, мы получаем 512 доступных для стека. Это дает нам место для 16384 потоков. Это также означает, что наш планировщик потоков должен манипулировать 16 384 потоками. Это значительно увеличивает вероятность того, что один из потоков будет голодать. Теперь, если один человек голодает, хорошо быть отстойным; если main голодает, отстой, чтобы быть ... всеми!

С nio у вас есть ... две темы. Главное и общение. (На самом деле вы могли бы сделать это даже без коммуникационного потока ...). Теперь на самом деле у вас, вероятно, есть нечто большее, поскольку у вас есть игровой цикл и все такое. Но все же 10 потоков намного проще планировать правильно, чем 16k потоков!

Nio не обязательно интуитивно понятен, но оно того стоит.

Единственное, что я хотел бы рассмотреть, если вы не собираетесь использовать nio, это иметь только 1 поток на соединение вместо двух. Вам не нужен второй для записи: у вас может быть поток с очередью, и он будет выполнять всю запись для всех клиентов. Это по крайней мере удвоит вашу пропускную способность на данный момент.

0 голосов
/ 18 июня 2015

Вы не должны думать ни о нагрузке по узлам, ни о количестве потоков.1) Если ваши игры масштабируются до миллионов пользователей, вам нужен кластер серверов, сбалансированный по нагрузке с помощью реестра

2) Каждый узел должен иметь низкую задержку, то есть каждый входящий игрок должен вычислять обновления мира (1 тик) за миллисекунды.,Очень выполнимоНе нужно иметь конфигурацию монстров для каждого узла.

3) вызывайте это 30 раз в секунду

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

С этим шаблоном загружается 10 000 одновременных игроков в игре в реальном времени на узел и +300 000 на узел на основе ходаигра.

Узким местом часто является IO.Используйте SSD для хранения базы данных.

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

HTH

Nuggeta admin - 100% Бесплатный высокопроизводительный многопользовательский сервер Java-игры

...