Подтвердить что ты не робот

Каков наилучший способ масштабирования приложения nodejs?

Основы

В настоящее время некоторые из моих друзей и я пытаемся разработать браузерную игру, сделанную в nodejs. Это многопользовательский шутер сверху вниз, и большая часть кода на стороне клиента и на стороне сервера находится в javascript. У нас есть хорошее общее направление, в которое мы хотели бы пойти, и нам очень интересно разрабатывать игру. Одна из наших целей при создании этой игры заключалась в том, чтобы сделать ее максимально возможной, чтобы обмануть. Делайте это, у нас есть вся логика игры, обработанная на стороне сервера. Клиент только отправляет свой вход на сервер через веб-сокет, а сервер обновляет клиент (также веб-сокет) тем, что происходит в игре. Вот начало нашей проблемы.

Вся математика на стороне сервера становится довольно массивной, и мы находим, что нам нужно каким-то образом масштабировать, чтобы обрабатывать больше, чем 10 игроков (мы хотим, чтобы иметь возможность принимать еще много). Сначала мы поняли, что можем просто масштабировать вертикально, как нам нужно, но поскольку nodejs является однопоточным, он может использовать только одно ядро. Это означает, что получение более жесткого сервера не поможет этой проблеме. Наше единственное решение - масштабировать по горизонтали.

Почему мы спрашиваем здесь

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

Подробнее

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

Четыре типа серверов

Мы разбиваем задачи на 4 разных типа серверов. Каждый из них будет выполнять определенную задачу.

Прокси-сервер

Прокси-сервер будет сидеть в передней части всего стека и быть единственным сервером, напрямую доступным из Интернета (потенциально может быть и больше). На нем будет haproxy, и он будет маршрутизировать все подключения к веб-серверам. Мы выбрали haproxy из-за его богатого набора функций, надежности и почти непревзойденной скорости.

Веб-сервер

Веб-сервер получит веб-запросы и будет обслуживать все веб-страницы. Они также будут обрабатывать создание/управление лобби и создание/управление игрой. Чтобы сделать это, они расскажут игровым серверам, какие у него лобби, какие пользователи находятся в этом лобби, и информацию об игре, которую они будут играть. Затем веб-серверы обновили игровые серверы о вводе пользователя, а игровой сервер обновил веб-серверы (которые затем обновили бы клиентов) того, что происходит в игре. Веб-серверы будут использовать сокеты TCP для связи с игровыми серверами любого типа управления, и они будут использовать сокеты UDP при общении об обновлениях игр. Это все будет сделано с nodejs.

Игровой сервер

Игровой сервер будет обрабатывать все математические игры и переменные обновления об игре. Игровые серверы также общаются с серверами db для записи отличной статистики о игроках в игре. Это будет сделано с nodejs.

Сервер db

Сервер db будет размещать базу данных. Эта часть на самом деле оказалась самой простой, так как мы нашли rethinkdb самый крутой db. Эта шкала легко и, как ни странно, оказалась самой легкой частью масштабирования нашего приложения.

Некоторые другие сведения

Если у вас возникли проблемы с тем, чтобы получить голову вокруг всего нашего getup, посмотрите на это, это полуточная диаграмма того, как мы думаем, что будем масштабироваться.

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

Некоторые вещи, которые мы не хотим

  • Мы не хотим использовать кластерный модуль nodejs. Он нестабилен (здесь ), и он не масштабируется на других серверах, а только на других процессорах. Мы хотели бы просто сделать скачок для горизонтального масштабирования.

Наш вопрос, подведенный

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

Спасибо

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

Спасибо!!

4b9b3361

Ответ 1

Следуя моим спонтанным мыслям по вашему делу:

Использование многоядерных приложений

node.js может масштабироваться и с несколькими ядрами. Как, например, вы можете читать здесь (или просто подумайте об этом: у вас есть один поток/процесс, работающий на одном ядре, что вам нужно, чтобы использовать несколько ядер? потоки или несколько процессов. Нажимайте работу из основного потока в другие потоки или процессы, и все готово).

Я бы сказал, что детское разработать приложение, которое не использует несколько ядер. Если вы используете некоторые фоновые процессы, хорошо, но если вы до сих пор работаете только в цикле основных событий node.js, вы должны определенно потратить некоторое время, чтобы сделать приложение масштабируемым по ядрам.

Реализация чего-то вроде IPC не так проста. Вы можете это сделать, но если ваш случай сложный, возможно, вам хорошо пойти с кластерным модулем. Это, очевидно, не ваш любимый, а просто потому, что что-то называется "экспериментальным", это не значит, что оно бесполезно. Просто попробуйте, возможно, вы даже можете исправить некоторые ошибки модуля на этом пути. Скорее всего, лучше использовать какое-то широко используемое программное обеспечение для сложных задач, чем изобретать новое колесо.

Вы также должны (если вы этого еще не знаете) использовать nextTick. Это позволяет основному циклу событий приостанавливать задачу с интенсивным процессором и выполнять другую работу в то же время. Вы можете прочитать об этом например здесь.

Общие мысли о вычислениях

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

Лучше всего сделать свой игровой код элегантным и быстрым. Подумайте, как эффективно решать проблемы. Если вы не можете что-то решить в Javascript эффективно, но проблема может быть легко извлечена, почему бы не написать небольшой компонент C вместо этого? Это также рассматривается как отдельный процесс, который уменьшает нагрузку на основной цикл событий node.js.

Proxy?

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

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

Эпилог

Остальное кажется мне более или менее прекрасным.

Ответ 2

Немного поздно в игре, но посмотрите здесь: http://goldfirestudios.com/blog/136/Horizontally-Scaling-Node.js-and-WebSockets-with-Redis

Вы не упомянули ничего общего с управлением памятью. Как вы знаете, nodejs не делит свою память с другими процессами, поэтому база данных в памяти является обязательной, если вы хотите масштабировать. (Redis, Memcache и т.д.). Вам нужно настроить подписчика на каждом node, чтобы принимать входящие запросы от Redis. Таким образом, вы можете масштабировать x nilo количество серверов (infront вашего HAProxy) и использовать данные, переданные из Redis.

Существует также этот node аддон: http://blog.varunajayasiri.com/shared-memory-with-nodejs Это позволяет вам обмениваться памятью между процессами, но работает только под Linux. Это поможет, если вы не хотите отправлять данные через локальные процессы все время или иметь дело с nodes ipc api.

Вы также можете преобразовать дочерние процессы в node для новой изоляции v8, чтобы помочь с дорогостоящими задачами, связанными с процессором. Например, игроки могут убивать монстров и получать довольно много лута в моей игре RPG действия. У меня есть дочерний процесс с именем LootGenerater, и в основном, когда игрок убивает монстра, он отправляет игру id, mob_id и user_id в процесс через IPC api .send по умолчанию. После того, как дочерний процесс получает его, он выполняет итерацию над большим таблицей добычи и управляет элементами (магазины до Redis или что-то еще) и завершает его.

Это помогает значительно ускорить цикл событий, и только одна идея, которую я могу придумать, чтобы помочь вам масштабировать. Но самое главное, вы захотите использовать систему базы данных в памяти и убедитесь, что ваша архитектура кода игры разработана вокруг любой используемой вами системы баз данных. Не делайте ошибку, которую я сделал, теперь переписывая все:)

Надеюсь, это поможет!

Примечание. Если вы решите пойти с Memcache, вам нужно будет использовать еще одну паб/подсистему.