Как мне спроектировать мой (в основном) текстовый игровой сервер? - PullRequest
18 голосов
/ 27 июля 2011

Подумайте, грязь / грязь, но, возможно, с аватарами или иллюстрациями локали.Мой язык выбора: ruby ​​.

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

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

за тиснение отличный ответ, я начал смотреть на внутренностинекоторых HTTP-серверов, поскольку веб-приложения обычно могут избежать проблем с многопоточностью из-за того, насколько тщательно проблема устранена самими серверами.

Я не хочу использовать EventMachine или GServer, потому что я невсе же понимаю что они делают .Как только у меня появится общее представление о том, как они работают, какие проблемы они решают и чем они полезны, я буду чувствовать себя комфортно.Моя цель здесь не «написать игру», а «написать игру и узнать, как работают некоторые вещи низкого уровня».Я также неясен в отношении границ определенных терминов;Например, является ли «приложения, не связанные с вводом / выводом» надмножеством «управляемых событиями приложений»?И наоборот?

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

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

То, как яделать это прямо сейчас можно с помощью IO#select, чтобы заблокировать список подключенных сокетов с таймаутом 0,1 секунд.Он помещает любую информацию, считываемую в потокобезопасную очередь чтения, и затем всякий раз, когда он достигает тайм-аута, он извлекает данные из поточно-безопасной очереди записи.Я не уверен, что время ожидания должно быть короче.Существует второй поток, который опрашивает очередь чтения потока обработки сокетов и обрабатывает «запросы».Это лучше, чем у меня изначально работало, но все же не могло бы быть идеальным.

Я разместил этот вопрос в Hacker News и получил ссылку на несколько ресурсов, через которые я работаю;что-нибудь подобное было бы замечательно:

Ответы [ 4 ]

13 голосов
/ 28 июля 2011

Хотя вы, вероятно, не любите это слышать, я все же рекомендовал бы сначала исследовать HTTP-серверы.Хотя программирование для них показалось вам скучным, синхронным и непостоянным, это только потому, что создатели серверов сделали свою работу, чтобы настолько хорошо скрыть от вас ужасные подробности - если подумать, веб-сервер такой не синхронно (это не значит, что миллионы людей должны ждать чтения этого поста, пока вы не закончите ... параллелизм :) ... и потому что эти звери так хорошо справляются со своей работой (да, я знаю, мы кричимих много, но, в конце концов, большинство HTTP-серверов являются выдающимися частями программного обеспечения), это определенная отправная точка для изучения, если вы хотите узнать об эффективной многопоточности.Операционные системы и реализации языков программирования или игр - еще один хороший источник, но, возможно, немного дальше от того, чего вы намерены достичь.

Если вы действительно хотите испачкать пальцы, я бы предложил сначала ориентироваться на что-то вроде WEBrick - оно поставляется с Ruby и полностью реализовано в Ruby, так что вы узнаете все оРубиновые потоки понятий там.Но имейте в виду, что вы никогда не приблизитесь к производительности решения Rack, установленного поверх веб-сервера, реализованного на C, такого как thin .

Так что если вы действительно хотитеЕсли быть серьезным, вам придется свернуть собственную реализацию сервера в C (++) и, возможно, сделать так, чтобы она поддерживала Rack, если вы собираетесь поддерживать HTTP.Я бы сказал, что это задача, особенно если вы хотите, чтобы ваш конечный результат был конкурентоспособным.Код на С может быть невероятно быстрым, но слишком просто быть невероятно медленным, он лежит в природе вещей низкого уровня.И мы еще не обсуждали управление памятью и безопасность.Но если это действительно ваше желание, сделайте это, но я бы сначала покопался в известных реализациях серверов, чтобы получить вдохновение.Посмотрите, как они работают с потоками (пул) и как они реализуют «сеансы» (вы хотели постоянство).Все, что вы хотите, можно сделать с помощью HTTP, даже лучше, если использовать его с умным интерфейсом REST. Существующие приложения, поддерживающие все функции, которые вы упомянули, являются живым доказательством этого.Так что идти в этом направлении было бы не совсем неправильно.

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

Независимо от того, используете ли вы его в качестве библиотеки или нет, изучите EventMachine и его концептуальную модель.Не обращать внимания на управляемый событиями («не блокирующий») ввод-вывод в вашем путешествии будет небрежно в контексте изучения / повторного изобретения правильных колес.Закуска для событийно-управляемого программирования, объясняющая преимущества node.js как веб-сервера .

В зависимости от ваших требований: асинхронная связь, несколько «подписчиков» реагируют на «события», которыецентрализованно опубликовано;хорошо, это действительно звучит как хороший кандидат для архитектуры, основанной на событиях / сообщениях .


Некоторые книги, которые могут быть полезны в вашем путешествии (только для Linux / C, но концепции универсальны):

(Это были классики)

  • Интерфейс программирования Linux - если вы просто собираетесь купить одну книгу,пусть это будет, я еще не совсем закончил, но это действительно удивительно и охватывает все темы, которые вам нужно знать для вашего приключения

Проекты, которые вы, возможно, захотите проверить:

  • Apache 2, thin, mongrel, nginx, lighttpd, ..., любой веб-сервер существует
  • EventMachine (извините:)
  • node.js
  • Эффективное сетевое взаимодействие в игре ( Quake 3 source )
3 голосов
/ 28 июля 2011

Рекомендую почитать немного о дизайне веб-сервера единорога.Это должно дать вам некоторое представление о обсуждении потоков и процессов.

http://unicorn.bogomips.org/DESIGN.html

http://tomayko.com/writings/unicorn-is-unix

2 голосов
/ 11 августа 2011

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

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

Время отклика также играет большую роль - я не думаю, что это так уж важно для игр в стиле MUD, но для веб-серверов или игр FPS это огромная проблема.

Сказав, что - единственные системы, аналогичные описанным вами, которые я знаю в любой детали, используют управляемую событиями модель программирования - клиенты запускают события, система обновляет свое внутреннее состояние и уведомляет затронутые клиенты.«Внутреннее состояние» фактически хранится в отдельном приложении, снова связываясь через сокеты - это позволяет масштабировать приложение, добавляя больше серверов для обработки взаимодействия с клиентом.Не уверен, что вам нужен этот уровень сложности.

Многопоточность действительно является реальной проблемой, и она создает трудно тестируемый код, поэтому, хотя ответ dash-tom-bang действительно немного не по теме, тестируемость вызывает серьезную проблему.

0 голосов
/ 28 июля 2011

Правильный путь - использовать тестовую разработку. Затем вы обнаружите, что вам нужно заново изобрести, именно в тот момент, когда вам это нужно.

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

...