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

Я разрабатываю многопользовательскую игру (модель клиент-сервер), и я застрял, когда дело доходит до масштабирования ее серверов.

Я понимаю, что большинство игр никогда не наберут 10 000+ игроков, и я не думаю, что моя тоже. Хотя, если мне очень повезет, я хочу развивать серверы, чтобы они не могли стать огромным препятствием позже.

Я много искал решение своей проблемы в Интернете, проверяя сообщения GDC об этом и проверяя другие сообщения на этом веб-сайте, но ни один из них, похоже, не решает мою конкретную проблему.

Моя текущая настройка приведена ниже, и все серверы написаны на C++ с использованием ENet в качестве моей сетевой библиотеки.

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

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

Лобби-сервер

Этот сервер обрабатывает список серверов, содержащий все серверы, которые в настоящее время работают.

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

  • Все клиенты отправляют пакет UDP на этот сервер, когда они хотят получить все серверы (которые находятся только на сервере). list screen), и сервер лобби отправляет обратно список всех серверов. Это случается не так часто, и лобби-сервер ограничен отправкой 4 серверов в секунду клиенту (а не огромным пакетом, содержащим все серверы).

Сервер входа

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

  • Все клиенты отправляют пакет UDP на этот сервер каждые 5 секунд, чтобы сказать, что они все еще живы, а также отправка того, в какой игре они находятся в данный момент. Затем сервер отправляет обратно их списки друзей, статусы онлайн / офлайн / в игре. Это делается для того, чтобы их друзья могли вести обновленный список того, кто из друзей находится в сети/не в сети/в игре.

  • Он отправляет сообщения только с действиями игрока, в противном случае, такими как создание учетной записи, вход в систему, изменение / сброс пароля, добавление/удаление/игнорирование друга, личные сообщения друзьям и т.д.

Мои вопросы

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

1. Теоретически могут ли они размещаться только на одном компьютере? Или это будет слишком много трафика для 10 000+ игроков?

2. Если их можно разместить на одном компьютере, не будет ли проблем с серверами для людей, которые живут далеко?
Не лучше ли в этом случае иметь серверы лобби и входа в систему для каждого региона мира? Плохо то, что игроки не смогут видеть серверы в США, если они живут в Европе, и что их учетная запись и предметы не будут существовать на других серверах.

3. Может быть, это надумано, но если бы я переписал оба сервера, чтобы вместо этого они находились на веб-сайте с базой данных, и чтобы клиент/игровой сервер вместо этого веб-запросы (например, HTTPS или вызов php с определенными заголовками), поможет ли это как-то решить мои проблемы?

Не уверен, какой ответ вы ожидаете здесь, кроме: это зависит. На множество факторов, и пост SO не место, чтобы проходить их все. Если это еще не проблема, не беспокойтесь об этом. Или проведите несколько стресс-тестов на своих серверах, чтобы увидеть, какую нагрузку они могут выдержать.

super 22.12.2020 19:15

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

marsh-wiggle 22.12.2020 19:15

Я согласен, что здесь будет сложно получить ответ. Это сводится к ограничению объема ненужного трафика, а также к написанию очень эффективного UDP-кода (что обычно означает асинхронность, основанную на IOCP, если мы говорим о Windows). Также избегайте выделения какой-либо памяти в подпрограммах UDP, вместо этого используйте статические буферы/пулы памяти.

Sven Nilsson 22.12.2020 20:25
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
3
1 229
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Все ваши проблемы и вопросы решает бессерверное облачное решение AWS Lambda например. или похожие. В этом случае масштабируемость не является вашей проблемой. Просто развивайте логику. Это сэкономит вам много времени.

Если вы хотите сделать серверы единым приложением, размещенным на вашем собственном сервере. Рассмотрите возможность использования чего-то вроде, например. Иди вместо С++. Он создан именно для этих целей. Я имею в виду высоконагруженные веб/сетевые сервисы.

Спасибо за ваш ответ! Я и раньше проверял AWS, но никогда не понимал, как он на самом деле решает мою проблему. Для каждого сервера входа и лобби у него есть свои данные для каждой машины, что означает, что все учетные записи и все игры в списке игр запускаются для каждого сервера. Если бы я добавил намного больше, это означало бы, что мне пришлось бы создать базу данных, расположенную где-то, которую используют все серверы, что снова замедлило бы работу серверов, потому что, если база данных находится в США, а игрок из (например) Китая, это будет очень медленным. Я понимаю, что сервис работает намного лучше для чего-то вроде игровых серверов.

MrPersson 23.12.2020 15:39

Я буду помнить о Go в будущем, если серверы окажутся слишком медленными.

MrPersson 23.12.2020 15:41

У вас есть два модуля (Логин и Лобби), определенные как отдельные сущности. Поскольку они могут размещаться на выделенном сервере, их легко реализовать с помощью бессерверного подхода. Вы спросите, как это решается. Главное здесь — вам не нужно думать об инфраструктурных вещах, таких как балансировка нагрузки, нехватка ресурсов и так далее. Это покрывается провайдером. Все сервисы, которые вы разрабатываете, включая базу данных, масштабируются «бесконечно» (мы можем использовать этот термин в предположении, что ваш проект требует ресурсов). Для входа также можно использовать Amazon Cognito. Они предоставляют 40 тысяч логинов бесплатно.

4xy 23.12.2020 16:09

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

4xy 23.12.2020 16:14

Потратив сегодня много часов на изучение всего, что касается AWS и моей проблемы, кажется, что использование AWS на самом деле является решением, как вы сказали. Это будет очень приятно узнать для дальнейшего развития, спасибо! Есть много проблем с AWS, которые нужно решить в первую очередь, например, входы в Steam кажутся немного сложнее реализовать, их сервисы должны быть разделены на разные регионы и т. д. Но это, вероятно, лучшее решение для масштабируемости, даже если для этого потребуются недели работы. Кроме того, DynamoDB кажется решением для всемирной базы данных.

MrPersson 23.12.2020 22:18

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

4xy 24.12.2020 11:27

Ну, это C++, и я пишу на Java, но, возможно, логика будет вам полезна, поэтому я расскажу вам, как я реализовал что-то подобное, но в казино.

В моем случае у меня есть 2 разных сокета в одной и той же серверной программе, один из сокетов - TCP, и он обрабатывает все входы в систему, регистры и платежи, а второй сокет - это UDP, и он обрабатывает реальную игру, в которую играют несколько плательщиков, тогда вы могли бы внутренне сгруппируйте все эти UDP-соединения в группы (возможно, массивы сокетов) для создания этих лобби. При этом весь ваш сервер представляет собой всего лишь один класс, который может работать на одном компьютере с использованием 2 портов (по одному на каждый сокет). Однако это не решает проблему пинга для людей, которые живут далеко. Если пинг является проблемой (не мой случай в казино), вы, вероятно, могли бы разместить базу своего региона сервера, но удалив логин, регистрацию и платежи вашего сервера и заменив его для подключения к центральному серверу (этот центральный сервер должен быть TCP и вы также можете реализовать сокет https, чтобы ваша веб-страница также могла подключаться к этому серверу и создавать учетные записи или платить вам напрямую из браузера)

извините, что еще больше испортил вам жизнь, но я надеюсь, что это поможет

Спасибо за ваш ответ! Таким образом, единственным изменением было бы заставить сервер входа и лобби использовать TCP вместо UDP в этом случае? Так как UDP уже используется в самой игре (на игровом сервере). Кроме того, сильно ли помогает TCP по сравнению с UDP в этих случаях? Что такое центральный сервер? Как это решает игроков, которые живут далеко?

MrPersson 23.12.2020 15:28

@MrPersson Ну, я бы сказал, что вам нужно больше, чем просто это изменение, во-первых, вам не нужен отдельный сервер только для лобби, на одном сервере могут размещаться как система входа в систему, так и лобби, однако входы и платежи должны всегда быть размещенным через TCP-соединение, потому что UDP не гарантирует получение пакета, и это большая проблема при входе в систему или оплате (на самом деле вам, вероятно, следует использовать сокет SSL через TCP, чтобы действительно защитить это соединение).

tomazu07 23.12.2020 21:39

@MrPersson Ни одна из предыдущих вещей не поможет с пингом, но оба являются обязательными, если вы хотите, чтобы ваше соединение было безопасным. Если вы хотите уменьшить пинг, просто разместите базу региональных игровых серверов (которая должна использовать UDP для уменьшения задержки) и заставьте эти серверы отправлять отчеты на ваш центральный сервер через TCP (чтобы отчеты не терялись). Центральный сервер — это сервер, который будет подключаться к вашей базе данных и действительно будет иметь доступ к важной информации (в данном случае это сервер, который отвечает за вход в систему, платежи и систему лобби).

tomazu07 23.12.2020 21:39

Я начал с одного сервера для входа в систему и лобби-сервера, но я думал, что они могут быть размещены на разных компьютерах с разным подключением к Интернету, таким образом, я разделил необходимые пакеты пополам, что является очень хорошим началом, если я считают, что они будут узкими местами. UDP с использованием ENet почти такой же, как и TCP, они гарантированы. Платежи осуществляются через https с использованием PayPal на моем веб-сайте, а мой сервер входа использует хэши паролей SHA с солью, которые являются временными. Я мог бы легко добавить шифрование к каждому пакету. Моя проблема не в безопасности.

MrPersson 23.12.2020 22:01

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

MrPersson 23.12.2020 22:02

@MrPersson Ну, во-первых, я не знаю, почему вы считаете, что наличие центрального сервера будет проблемой, вам нужно, чтобы он отображал все лобби во всех регионах, а также, если сервер получает только логины и уведомления от игровых серверов, тогда вы потребуется более миллиона игровых серверов, чтобы создать какие-либо проблемы для вашего центрального сервера, и если вам удастся сделать свою игру такой популярной, вы уже разбогатеете. Если у вас есть центральный сервер, вашим узким местом будет не количество пользователей, а количество игровых серверов. Кроме того, я бы по-прежнему использовал TCP для входа в систему, но это на ваше усмотрение.

tomazu07 24.12.2020 06:16

Другие вопросы по теме