Как работает сервер? Как работает веб-сервер Технология работы с сервером как работает.

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

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

Ниже мы расскажем о некоторых интересных и нетривиальных случаях.

Обнаружение неполадок

Регистрация проблемы чаще всего происходит после обращения клиентов в службу технической поддержки посредством тикет-системы.

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

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

Если становится ясно, что проблема аппаратная (например, сервер не видит часть оперативной памяти), то на этот случай у нас всегда есть в резерве аналогичная серверная платформа.

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

Примеры неполадок и способы их устранения

Сбой в работе сети на сервере

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

Дело в том, что при первоначальной установке операционной системы, MAC-адреса сетевых карт записываются в специальный файл, расположенный по адресу: /etc/udev/rules.d/70-persistent-net.rules.

При старте операционной системы этот файл сопоставляет имена интерфейсов MAC-адресам. При замене сервера на резервный, MAC-адреса сетевых интерфейсов уже не совпадают, что и приводит к неработоспособности сети на сервере.

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

Операционная система, не найдя этого файла, автоматически сгенерирует аналогичный и сопоставит интерфейсы уже с новыми MAC-адресами сетевых карт.

Перенастройки IP-адресов после этого не требуется, сеть сразу начнет работать.

Плавающая проблема с зависаниями

Однажды к нам на диагностику поступил сервер с проблемой случайных зависаний в процессе работы. Проверили логи BIOS и IPMI - пусто, никаких ошибок. Поставили на стресс-тестирование, нагрузив все ядра процессора на 100%, с одновременным контролем температуры - завис намертво через 30 минут работы.

При этом процессор работал штатно, значения температуры не превышали стандартных при нагрузке, все кулеры были исправны. Стало ясно, что дело не в перегреве.

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

Заменив модуль на новый, мы поставили сервер на тест повторно, однако нас ждало фиаско - сервер вновь завис, выдав ошибки уже по другому модулю ОЗУ. Заменили и его. Еще один тест - еще раз завис, вновь выдав ошибки по оперативной памяти. Внимательный осмотр слотов ОЗУ не выявил никаких дефектов.

Оставался один возможный виновник проблемы - центральный процессор. Дело в том, что контроллер оперативной памяти расположен именно внутри процессора и именно он мог давать сбой.

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

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

Мнимое зависание сервера при установке ОС

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

К нам обратился пользователь с жалобой на зависание сервера при попытке установки операционной системы Windows Server 2008 R2. После успешного запуска инсталлятора, сервер прекращал реагировать на мышь и клавиатуру в KVM-консоли. Для локализации проблемы подключили к серверу физическую мышь и клавиатуру - все то же самое, инсталлятор запускается и перестает реагировать на устройства ввода.

На тот момент этот сервер у нас был одним из первых на базе материнской платы X11SSL-f производства Supermicro. В настройках BIOS был один интересный пункт Windows 7 install, выставленный в Disable. Поскольку Windows 7, 2008 и 2008 R2 разворачиваются на одном и том же инсталляторе, выставили этот параметр в Enable и чудесным образом мышь и клавиатура наконец-то заработали. Но это было лишь только начало эпопеи с установкой операционной системы.

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

Википедия сообщила, что проблема решается отключением в BIOS поддержки USB 3.0 (XHCI-контроллера). Когда мы открыли документацию к материнской плате, нас ожидал сюрприз - разработчики решили полностью отказаться от контроллера EHCI (Enhanced Host Controller Interface) в пользу XHCI (eXtensible Host Controller Interface). Иными словами, все порты USB на этой материнской плате являются портами USB 3.0. И если отключить контроллер XHCI, то мы этим самым отключим и устройства ввода, сделав невозможным работу с сервером и соответственно установку операционной системы.

Поскольку серверные платформы не были оборудованы приводами для чтения CD/DVD дисков, единственным решением проблемы стало интегрирование драйверов непосредственно в дистрибутив операционной системы. Только интегрировав драйвера контроллера USB 3.0 и пересобрав установочный образ, мы смогли установить Windows Server 2008 R2 на этот сервер, а этот случай вошел в нашу базу знаний, чтобы инженеры не тратили лишнее время на бесплодные попытки.

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

Устройство представляет собой систему хранения данных c двумя дисковыми контроллерами и сетевыми интерфейсами для работы по протоколу iSCSI. Помимо этих интерфейсов присутствует MGMT-порт для удаленного управления.

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

  • «iLO» у Hewlett-Packard;
  • «iDrac» у Dell;
  • IPMI у Supermicro.
Функционал у них приблизительно одинаков - мониторинг состояния сервера и доступ к удаленной консоли. Соответственно большая скорость канала им не требуется - 10 Мбит/с вполне достаточно для комфортной работы. Именно эта услуга и была заказана клиентом. Мы проложили соответствующую медную кроссировку, и настроили порт нашего сетевого оборудования.

Для ограничения скорости порт просто настраивается как 10BASE-T и включается в работу, имея максимальную скорость в 10 Мбит/с. После того, как все было готово - мы подключили MGMT-порт дисковой полки, но клиент почти сразу сообщил, что у него ничего не работает.

Проверив состояние порта коммутатора, мы обнаружили неприятную надпись «Physical link is down». Такая надпись говорит, что имеется проблем с физическим соединением между коммутатором и подключенным в него клиентским оборудованием.

Плохо обжатый коннектор, сломанный разъем, перебитые жилы в кабеле - вот небольшой перечень проблем, которые приводят именно к отсутствию линка. Разумеется, наши инженеры сразу взяли тестер витой пары и проверили соединение. Все жилы идеально прозванивались, оба конца кабеля были обжаты идеально. К тому же, включив в этот кабель тестовый ноутбук, мы получили как и положено соединение со скоростью 10 Мбит/с. Стало ясно, что проблема на стороне оборудования клиента.

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

Нашли на сайте производителя оригинальную инструкцию по эксплуатации, чтобы уточнить - возможно ли со стороны программного обеспечения «погасить» данный порт. Однако такой возможности не предусматривалось - порт в любом случае поднимался автоматически. Несмотря на то, что подобное оборудование должно всегда поддерживать Auto-MDI(X) - иными словами правильно определять какой кабель включен: обычный или кроссовер, мы эксперимента ради обжали кроссовер и включили в тот же порт коммутатора. Пробовали принудительно выставлять параметр дуплекса на порту коммутатора. Эффект был нулевой - линка не было и идеи уже заканчивались.

Тут кто-то из инженеров высказал абсолютно противоречащее здравому смыслу предположение, что оборудование не поддерживает 10BASE-T и будет работать только на 100BASE-TX или даже на 1000BASE-X. Обычно любой порт, даже на самом дешевом устройстве совместим с 10BASE-T и вначале предположение инженера отмели как “фантастику”, но от безысходности решили попробовать переключить порт в 100BASE-TX.

Нашему удивлению не было предела, линк мгновенно поднялся. Чем именно обусловлено отсутствие поддержки 10BASE-T на порту MGMT остается загадкой. Такой случай - очень большая редкость, но имеет место быть.

Клиент был удивлен не меньше нашего и очень благодарил за решение проблемы. Соответственно ему так и оставили порт в 100BASE-TX, ограничив скорость на порту непосредственно с помощью встроенного механизма ограничения скорости.

Отказ турбин охлаждения

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

Оказывается, что у сервера производства Hewlett-Packard отказало две турбинки охлаждения из шести. Сервер при этом включается, выдает ошибку по охлаждению и сразу выключается. При этом на сервере располагается гипервизор с критичными сервисами. Для восстановления штатной работы сервисов требовалось выполнить срочную миграцию виртуальных машин на другую физическую ноду.

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

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

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

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

А где же диски?

В некоторых случаях причина проблемы порой настолько нетривиальна, что на ее поиск уходит очень большое количество времени. Так и получилось, когда один из наших клиентов пожаловался на случайный отвал дисков и зависание сервера. Аппаратная платформа - Supermicro в корпусе 847 (форм-фактора 4U) с корзинами для подключения 36-ти дисков. В сервере было установлено три одинаковых RAID-контроллера Adaptec, к каждому подключено по 12 дисков. В момент возникновения проблемы, сервер переставал видеть случайное количество дисков и зависал. Сервер вывели из продакшн и приступили к диагностике.

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

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

Переустановили контроллер в другой слот, заменили бэкплейн и SATA-кабели от контроллера до бэкплейна. Неделя тестов и снова диски выпали - сервер вновь завис. Обращение в поддержку Adaptec результатов не принесло - они проверили все три контроллера и проблем не обнаружили. Заменили материнскую плату, пересобрав платформу чуть ли не с нуля. Все, что вызывало малейшие сомнения заменили на новое. И проблема вновь проявилась. Мистика да и только.

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

Заключение

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

Вот такие забавные случаи были в нашей практике.
А с какими сталкивались вы? Добро пожаловать в комментарии.

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

Составляющие клиент-серверной схемы

Посмотрим, из чего состоит сам сервер и без каких внешних компонент он не может обходиться. Во-первых, сервер теряет свой смысл в отсутствие клиентов. Принцип работы сервера - реализовывать нужды клиентов. Клиент формирует требования к серверу и берет на себя некоторую долю его работы. Поэтому чаще говорят не просто о сервере, а о системе клиенты-сервер. Клиент составляет запросы к серверу, посредством которых изъявляет свою волю. Посему следующим, вторым компонентом системы будет тот формальный язык, на котором эти запросы составляются. Этих языков великое множество и выбор того или иного напрямую зависит от сервера. Запросы до сервера должны как-то доставляться. Третий элемент - канал связи клиента и сервера, по которому передаются данные. Это чаще всего либо локальная сеть, либо Интернет, либо локальные связи одной машины. Пришедший запрос сервер должен как-то принять и распознать. Принимающее устройство - так называемый внешний интерфейс, представляет собой несколько портов, которые сервер непрерывно (или не непрерывно) слушает. Принятые запросы отправляются в программную часть сервера, где и обрабатываются в соответствии с тем, как сервер запрограммирован. И в зависимости от принятого запроса, запускается тот или иной сервис с теми или иными начальными данными. Сервисы и будут последней составляющей системы. После окончания работы сервиса результат выполнения отсылается клиенту по тому же каналу связи. Или, если сервис интерактивный, то и в процессе его работы будет интенсивный обмен данными по каналу «клиент-сервер».

Для чего нужен сервер

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

Плюсы и минусы модели

Плюсы очевидны - сам принцип работы сервера обеспечивает удобство работы с системой, простоту управления ею, правильное распределение нагрузки на машины. А минусом является язык запросов и связанные с ним компоненты. Если пользователь случайно или умышленно отсылает на сервер неверно сформулированный запрос, то если такая ошибка не была предусмотрена программистом, система даст сбой. Сведущие люди составляют заведомо неверные запросы так, чтобы система, призванная выдавать клиенту прогноз погоды, вывела злоумышленнику, например, данные кредитных карт всех пользователей (если, конечно, за данные карт и за прогноз погоды отвечает один и тот же сервер). И счастливый злоумышленник сначала идёт и перечисляет себе все деньги всех пользователей сервиса, а затем долго и вдумчиво убегает от управления «К», расследующего это преступление.

Безопасность

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

Как правило, у рядового пользователя такие понятия, как «веб-сервер» или «хостинг», ассоциируются с чем-то абсолютно непонятным. Между тем, ничего сложного в этом вопросе нет. Попытаемся объяснить, что собой представляет web server, зачем он нужен и как работает, особо не вдаваясь в технические подробности, а, так сказать, на пальцах. Отдельно остановимся на вопросе о том, как создать и настроить такой сервер на домашнем компьютерном терминале или ноутбуке.

Что такое веб-сервер?

Самое главное в данном вопросе - понять, что сервер такого типа является не чем иным, как компьютером в интернете с соответствующим установленным программным обеспечением.

Но это абсолютно не значит, что в домашних условиях нельзя создать собственную конфигурацию. Поскольку у нас более распространенными являются операционные системы Windows, вопросы о том, как создать веб-сервер на Ubuntu (Linux), рассматриваться не будут.

Для чего нужны web-серверы?

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

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

Как это все работает?

Все пользователи привыкли, что для входа на какой-то ресурс в интернете (веб-страницу), на котором располагается информация определенного типа, в адресной строке просто вводится префикс www (или http) и последующее имя. Но никто не задумывается о том, каким образом web server понимает запрос и выдает результат.

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

Для доступа в интернет применяются программы, называемые веб-браузерами. Они переводят пользовательский запрос в цифровой код, распознаваемый веб-сервером. Сервер его обрабатывает и выдает ответ в соответствующем коде, а браузер уже преобразует миллионы нулей и единиц в нормальный вид с текстовой, графической, звуковой или видеоинформацией, которая размещается на странице.

Самые популярные web-серверы

Из всего серверного программного обеспечения, как считается, самыми распространенными являются Apache и Microsoft IIS. Первый является более популярным и в большей степени используется в UNIX-подобных системах, хотя и может устанавливаться в среду Windows. Кроме того, сервер Apache является абсолютно бесплатным программрным обеспечением и совместим практически со всеми известными операционными системами. Однако, как отмечается, предназначено это ПО в основном для профессиональных программистов и разработчиков.

Программный продукт от Microsoft рассчитан на среднестатистического пользователя, который установить и настроить такой веб-сервер для Windows сможет без дополнительной помощи квалифицированного специалиста.

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

Веб-сервер на домашнем компьютере: установка

Для инсталляции потребуется скачать специальный серверный пакет, сокращенно обозначаемый как WAMP, в который входит три основных компонента:

  • Apache - программная оболочка сервера, которая может работать самостоятельно, но только в случае отсутствия на размещаемых страницах динамического контента.
  • PHP - язык программирования, используемый надстройками для управления серверами с динамическим содержимым вроде WordPress, Joomla, Drupal.
  • MySQL - унифицированная система управления базами данных, используемая, опять же, при создании сайтов с динамическим контентом.

Инсталляцию можно произвести из пакета WampServer. Для этого достаточно следовать указаниям «Мастера», который на одной из стадий предложит выбрать интернет-браузер, который будет использоваться по умолчанию.

Для этого нужно будет перейти в папку с исполняемым файлом браузера (если это не Internet Explorer, обычно она располагается в директории Program Files). Попутно сам браузер следует добавить в список исключений брэндмауэра Windows. На финишной стадии ставится галочка напротив пункта немедленного запуска, после чего в системном трее появится соответствующий значок, на который нужно нажать и изменю выбрать запуск локального хоста (localhost).

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

Пример настройки и тестирования сервера

Настройка веб-сервера несколько сложнее. Сначала в меню системного трея выбирается переход в папку WWW (место хранения надстроек или файлов HTML). После этого прописать следующий текст в «Блокноте»:

WAMP тест!

Привет!

"; ?>

Можете просто скопировать текст в «Блокнот» и сохранить файл под именем index.php в той самой папке WWW (хотя можно обойтись и без того, поскольку этот шаг применяется исключительно для проверки локального хоста). Вместо приветствия можете вставить любой другой текст или фразу.

Затем в браузере нужно обновить страницу (F5), после чего на экране отобразится содержимое. Но для других компьютеров страница будет недоступна.

Чтобы открыть доступ, нужно изменить файл httpd.conf, прописав в разделе, который начинается с следующие строки:

Order Allow,Deny

Вместо послесловия

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

Привет, Хабр! Я Андрей Фролов, ведущий программист, работаю в Mail.Ru над Next-Gen MMORPG Skyforge. Вы могли читать мою статью про архитектуру баз данных в онлайн-играх. Сегодня я буду раскрывать секреты, касающиеся устройства сервера Skyforge. Постараюсь рассказать максимально подробно, с примерами, а также объясню, почему было принято то или иное архитектурное решение. По нашему серверу без преувеличения можно написать целую книгу, поэтому для того, чтобы уложиться в статью, мне придется пройтись только по основным моментам.

Обзор

  • Сервер - это почти два миллиона строк кода на Java. Для соединения с сервером и отображения красивой картинки используется клиент, написанный на C++.
  • Свой вклад в серверный код внесли полсотни программистов. Код писался в течение многих лет лучшими специалистами российского «православного» геймдева. В нем собраны все самые удачные идеи со всего мира.
  • На текущий момент у нас написано около 5200 автоматических тестов, налажен continuous integration и нагрузочное тестирование с помощью ботов.
  • Сервер умеет запускаться и работать на десятках и сотнях серверов, поддерживать игру сотен тысяч человек одновременно. Мы решили отказаться от традиционной для MMO техники шардирования и запустить всех игроков в один большой мир.

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

Сервисная архитектура

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

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

Третья большая проблема - это многопоточность. Как известно, лучший способ сладить с многопоточностью - это избежать ее. Deadlock, livelock, lock contention и другие милые сердцу программиста проблемы можно обойти, если архитектура сервера будет избавлять вас от необходимости синхронизировать потоки вручную. В идеале программист вообще должен писать простой однопоточный код и не задумываться о такого рода вещах.

Отсюда родилась наша универсальная структура сервера, которая используется в Skyforge:

  • Существует пул физических серверов, на которых будет запускаться игра. Этот набор серверов и наше серверное приложение, которое на них запущено, называется Realm.
  • На каждом сервере запускается серверное приложение (JVM), называемое ролью. Роли бывают разные: аккаунт-сервер, игровая механика, чат и т.д. Каждая роль берет на себя большой кусок функционала. Некоторые роли существуют в единственном числе, некоторые запускаются в нескольких экземплярах.
  • Роль состоит из набора сервисов. Сервис - это обычный поток (thread), который занимается своей, специфичной для него задачей. Примером сервиса может служить сервис авторизации, сервис резервирования имен, балансировщик нагрузки и т.п. Каждый сервис ничего не знает о физическом расположении других сервисов. Они могут быть рядом, а могут быть на другой физической машине. Сервисы взаимодействуют через систему сообщений, которая скрывает от них такого рода подробности.
  • Каждый сервис состоит из набора модулей. Модуль - это «кусок функциональности», у которого есть один метод tick(). Примером модуля может быть модуль статистики, модуль исполнения транзакций, модуль синхронизации времени. Вся работа сервиса заключается в том, чтобы в бесконечном цикле поочередно вызывать метод tick() у своих модулей. Один такой цикл называется «кадр сервера». Мы считаем показатель хорошим, если кадр сервера колеблется в пределах от 3 до 20 мс.
  • Вся эта структура описывается в XML-файлах. Системе запуска надо просто «скормить» название роли. Она найдет соответствующий файл, запустит все нужные сервисы и отдаст им списки модулей. Сами модули создадутся с помощью java reflection.

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

Основные сервисы

Есть некоторый набор сервисов, который несет основную игровую нагрузку. Каждый из серверов должен уметь масштабироваться. В идеале - до бесконечности. К сожалению, писать серверы так, чтобы они масштабировались, это непростая задача. Поэтому мы начали с того, что сделали основные сервисы масштабируемыми, а всякую дополнительную мелочь, которая не несет основной нагрузки, оставили на потом. Если у нас будет очень много пользователей, то и их нам придется улучшать для обеспечения возможности масштабирования.
  • Аккаунт-сервис. Отвечает за авторизацию и подключение новых клиентов.
  • Сервер игровой механики. Тут происходит, собственно, сама игра. После прохождения авторизации клиент подключается сюда и тут играет. С другими сервисами клиент напрямую не взаимодействует. Таких сервисов можно и нужно запускать несколько десятков, а то и сотен. Именно эти сервисы несут основную нагрузку.
  • Сервисы баз данных. Эти сервисы выполняют операции над данными игровых персонажей, их предметами, деньгами, прогрессом развития. Их обычно запускается несколько штук. Подробнее об архитектуре баз данных можно прочитать в моем прошлом докладе. (habrahabr.ru/company/mailru/blog/182088)
  • Чат. Занимается роутингом сообщений чата между пользователями.
  • Все остальные сервисы. Их несколько десятков, и они обычно не создают сильной нагрузки, поэтому не требуют обособленных серверов.

Сеть

Под словом «сеть» я подразумеваю систему доставки сообщений от одного сервиса к другому или от одного объекта к другому. Исторически так сложилось, что у нас существует сразу две такие системы. Одна основана на сообщениях. Вторая система основана на удаленном вызове процедур (RPC). В Skyforge система сообщений применяется внутри сервиса игровой механики, чтобы послать какое-то сообщение от аватара к мобу, а также для общения клиента и сервера. RPC используется для общения между сервисами.

Сообщения
Все объекты, которые хотят посылать или принимать сообщения, называются абонентами. Каждый абонент регистрируется в общей директории и получает уникальный идентификатор - адрес. Любой, кто хочет послать сообщение какому-либо абоненту, должен указать адреса «откуда» и «куда». Сетевой движок знает, где находится абонент, и доставляет ему сообщение. Сообщение - это Java-объект, у которого есть метод run(). При отправке этот объект сериализуется, прилетает к целевому абоненту, там десериализуется, а затем вызывается метод run() над целевым абонентом.

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

RPC
Удаленный вызов процедур или RPC появился, чтобы решить проблему цепочек сообщений.
Основная идея заключается в использовании кооперативной многозадачности (Coroutine, Fibers). Тому, кто не знаком с это концепцией, для понимания темы советую заглянуть в «Википедию». en.wikipedia.org/wiki/Coroutine .
Сервис, который хочет, чтобы его могли вызывать через удаленный вызов процедур, должен реализовывать специальный интерфейс и зарегистрировать в специальной директории. Тогда любой желающий может попросить директорию дать ему интерфейс этого сервиса, и директория вернет специальный враппер над сервисом. Вызывать сервисы по RPC можно только внутри файбера (coroutin), т.е. специального контекста исполнения, который можно прерывать и возобновлять в точках разрыва. При вызове методов враппера он будет посылать RPC вызовы на удаленный сервис, прерывать текущий файбер в ожидании ответа и возвращать результат, когда удаленный сервер ответит.

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

Сериализация
Чтобы у нас работала система посылки сообщений и удаленный вызов процедур, нам нужен клиент-серверный протокол и способ сериализации/десериализации объектов. Напомню, что у нас есть необходимость пересылать команды и данные с клиента на сервер, т.е. из C++ в Java и обратно. Для этого мы по Java-классам генерируем их копии в C++, а также генерируем методы для сериализации и десериализации объектов в байтовый поток. Код для сериализации встраивается прямо внутрь классов и обращается к полям класса напрямую. Таким образом, сервер не тратит процессорное время на обход классов с помощью reflection. Все это мы генерируем с помощью самописного плагина для IntelliJ IDEA. Внутрисерверный протокол для общения между сервисами полностью аналогичен клиент-серверному протоколу.

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

Игровая механика

Основной сервис, который был бы вам интересен, это сервис игровой механики. Именно там выполняется весь код, непосредственно связанный с игрой, именно там моделируется весь игровой мир, летают фаерболы и «грабятся корованы».
Карты и балансировка нагрузки
На серверах игровой механики создаются карты, на которых, собственно, находятся игроки, мобы и происходит все веселье. У каждой карты есть лимит на количество игроков, которые могут на ней находиться. Например, лимит может быть равен единице для персональных приключений, 10–30 для групповых активностей и 250 для больших карт. Что происходит, если на карту захочет попасть еще один игрок, когда лимит исчерпан? Тогда будет создана еще одна копия той же самой карты. Игроки с этих карт не будут видеть друг друга, не будут друг другу мешать. Т.е. в каком-нибудь игровом городе могут быть тысячи человек, но там не будет тесно. Такой способ организации игроков называется «каналы».

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

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

Аватары и мобы
Аватар - это персонаж, которым управляет игрок, моб - это монстр, которого игрок убивает. Это весьма разные, но часто очень похожие сущности. И моб, и аватар умеют ходить по карте, у них есть здоровье, они могут использовать заклинания и т.п. Только аватаром управляет игрок, а у моба есть свой мозг. Кроме того, на картах есть множество всяких сундуков, растений и других интерактивных сущностей. Очень часто нужно делать некую функциональность и цеплять ее к разным сущностям. Для этих целей мы используем компонентный подход, собирая игровую сущность из набора функциональностей. Поясню на примере. Допустим, у игрока и моба есть показатель здоровья. В таком случае мы оформляем элемент «здоровье» как отдельный Java-класс, в котором описываем, как здоровье себя ведет: как оно может уменьшаться, как восстанавливаться, какие есть таймеры и т.п. Потом мы просто складываем все функциональности в специальную HashMap внутри сущности и берем ее оттуда по необходимости. Таких компонент у нас существуют сотни, на них собрана половина игровой механики.

Так как серверное приложение очень сложное, неизбежно возникновение ошибок. Нужно сделать так, чтобы возникновение ошибки, даже необработанного NullPointerException, не приводило к падению сервера. Можно ошибку просто залогировать и пойти дальше, но если ошибка возникнет посреди какого-то длинного действия над аватаром, то аватар может оказаться в сломанном и неконсистентном состоянии. Тут нам на помощь приходит концепция под названием «локаль». Локаль - это контекст, внутри которого объекты могут ссылаться друг на друга. Объекты из одной локали не могут ссылаться на объекты из другой. Если из локали вылетает необработанное исключение, то локаль удаляется целиком. Аватары, мобы и другие сущности являются локалями, удаляются целиком и не могут держать ссылок на других аватаров и мобов. Поэтому все взаимодействие между аватарами и мобами идет через систему сообщений, хотя они находятся вместе на одной машине и в теории могли бы держать друг на друга прямую ссылку.

Репликация
Моделировать игровой мир нужно не только на сервере, но и частично на клиенте. Например, клиенту нужно видеть других игроков и мобов, которые находятся рядом с ним. Для этого используется механизм клиент-серверной репликации, когда с сервера клиентам рассылаются обновления окружающего игрового мира. Делается это с помощью генератора кода, который встраивает отсылку обновлений в сеттеры серверных Java-объектов. Вокруг игрока создается круг определенного радиуса, и если кто-то, например другой аватар, попадает в этот круг, он начинает реплицироваться на клиент. С репликацией есть фундаментальная проблема. Если в одном месте столпится N аватаров, то на каждого из них нужно будет посылать N реплик. Таким образом возникает квадратичная зависимость, что ограничивает количество аватаров, которые могут собраться в одном месте. Именно из-за этой фундаментальной квадратичности клиенты всех ММО тормозят в столицах. Мы избегаем этой проблемы, ограничивая количество игроков на карте и распределяя их по каналам.
Ресурсная система
В игре существуют сотни и тысячи заклинаний, предметов, квестов и других подобных сущностей. Как вы, наверное, догадываетесь, программисты не пишут все сотни квестов, это делают геймдизайнеры. Программист разрабатывает один Java-класс квеста, а описания всех квестов с их логикой, задачами и текстами содержатся в XML-файлах, называемых ресурсами. При старте сервера мы загружаем эти ресурсы и на их основе собираем Java-классы с описанием мира. Этими классами уже может пользоваться сервер. Примерно такая же система существует и на стороне клиента, только там ресурсы не грузятся из XML-файлов, а просто загружается заранее созданный «кусок памяти», содержащий все нужные объекты и ссылки между ними. Ресурсных файлов у нас существует несколько сотен тысяч, но их загрузка на сервере занимает около двух минут. На клиенте же все грузится за секунды. Система очень навороченная, поддерживает такие фичи, как прототипы и наследование, вложенные описатели и т.п. Поверх ресурсной системы у нас созданы специализированные программы для редактирования карт и остальных игровых сущностей.

Сервер в действии

Давайте теперь на примерах рассмотрим несколько сценариев того, как работает вся эта система в действии.
Убить собачку
Классический тест, который мы всегда проводим, если сильно изменили инфраструктуру и хотим проверить, что все работает, называется «Убить собачку». Нужно зайти клиентом на сервер и убить там какого-либо моба. Этот тест покрывает практически все основные моменты сервера и служит прекрасным примером для того, чтобы сложить все вышесказанное вместе. Давайте по пунктам разберем, что и как происходит при убиении несчастной собачки. Конечно, некоторые шаги упрощены, но это не критично для понимания.
  • Клиент посылает на аккаунт-сервер сообщение: «Хочу войти в игру».
  • Аккаунт-сервер запрашивает базу данных, проводит авторизацию и запрашивает у балансировщика карту, на которой игрок был в последний раз.
  • Балансировщик выбирает карту из уже загруженных или создает новую на наименее загруженном сервере игровой механики.
  • Клиент подключается к той механике, где для него была создана карта. Пока он подключается, для него загружается его аватар.
  • Сервер начинает реплицировать все объекты вокруг аватара на клиент. Клиент рисует шикарную картинку и посылает на сервер команды, которые посылает игрок.
  • Игрок начинает бегать по карте, а сервер перемещает его по миру и реплицирует изменения окружающей действительности. Игрок находит какого-либо моба и нажимает кнопку «ударить».
  • Команда «удар» прилетает на сервер, на сервере выполняется проверка, что удар возможен, и мобу отправляется сообщение о нанесении повреждений.
  • Команда «нанести повреждения» отрабатывается на мобе, просчитывает все резисты и другие подобные вещи, потом берет функциональность «здоровье» и списывает какое-то количество.
  • Клиенту посылается ответ с подтверждением нанесения урона, клиент рисует удар.
Масштабирование
Давайте зайдем с другой стороны и посмотрим, как сервер ведет себя под нагрузкой.
  • 0 клиентов. Если на сервере никого нет, его можно запускать одним приложением с минимальными настройками и без карт. На сервере нет никакой активности, и большую часть времени он простаивает.
  • 1 клиент. Для одного клиента приходится создавать карту, мобов, серверные объекты, которые начинают потреблять память и процессорное время для своей жизни.
  • 500 клиентов. 500 клиентов обычно уже достаточно много, чтобы процессорного времени одной персоналки не хватало для работы сервера. Приходится запускать realm на нескольких машинах или на более мощных серверах.
  • 10000 клиентов. 10000 клиентов требуют уже нескольких серверов. Так как большая часть нагрузки приходится на игровые механики, нужно запускать realm с дополнительными сервисами игровой механики.
  • 100000 клиентов. При 100000 одновременных игроков больше половины серверов заняты игровой механикой.
  • Клиентов больше, чем железа. Если вдруг игроков станет еще больше, а железо у нас вдруг кончится, то придется ограничивать вход людей в игру, пока подвозят новые серверы. Для этого существует очередь на вход, которая заставляет игроков ждать, когда сервер будет готов их принять. Эта очередь гарантирует, что одновременно один realm не может содержать игроков больше, чем мы готовы принять. В очередь игроков могут начать ставить и в том случае, если из-за бага или еще по каким-либо причинам сервер вдруг стал работать медленнее определенного порога. Лучше сделать приемлемый сервис для ограниченного числа клиентов, чем упасть для всех.

Заключение

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

Если ежедневно используется компьютер, который подключен к сети, если на мобильном гаджете тоже подключен Интернет, то каждый пользователь время от времени сталкивается со словом – «сервер». Причем это слово может встречаться в разных сочетаниях, и не каждый пользователь понимает, о чем идет речь. Что же скрывается до словом «сервер», да и зачем он пользователям нужен?

Под понятием «сервер» может скрываться аппаратное устройство и программное обеспечение для него (аппаратный и виртуальный). Аппаратный сервер – это отдельный компьютер. Он нужен для обеспечения работы других ПК и офисной техники. Виртуальный сервер – это ПО. При этом конкретный сервер объединяет эти два вида.

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

Работу больших компаний, на которых установлено много электронного оборудования, уже трудно представить без объединения все этих устройств в одну сеть. Сервер на предприятии позволяет удаленного управлять офисной техникой и позволяет взаимодействовать ПК между собой.

Поломка сервера или сбой в его работе может закончиться катастрофой

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

Сервер обеспечивает выход в Сеть. Все сайты хранятся на серверах. Это обеспечивает виртуальный хостинг. Такую услугу предоставляют хостинговые компании.



Статьи по теме