Погружаясь в любимую игру, кто угодно, несомненно, будет не особенно рад, если у него неожиданно выключится компьютер из-за пропавшего в доме электричества или, не дай бог, вышедшего из строя компонента. В случае с играми, требующими постоянного подключения к интернету, список угроз дополняется сетевыми проблемами. Именно об этом я и хочу поговорить, рассмотрев весь путь — от дата-центра до изображения на мониторе игрока с технической точки зрения и немного рассказав, про то, как правильно диагностировать возможные неполадки.
Подавляющее большинство сетевых игр, как ММО, так и однопользовательских, но требующих онлайн-аутентификации (не путать с авторизацией!), для работы используют инфраструктуру, состоящую из серверов и сетевого оборудования, расположенного в дата-центрах, которые обрабатывают запросы игроков и отправляют в ответ свои данные — например, разрешение на вход от логин-сервера или игровую информацию для уже вошедших в игру.
Принципиально всё это обычно состоит из следующих частей:
Серверы, как вы наверняка знаете — это специализированные компьютеры, на которых выполняются все операции, связанные с сервисами, относящимися к нашей игре. Функционально их можно разделить на два вида — серверы приложений и серверы баз данных. Внутри первых крутятся программы, реализующие всю логику — логин, отдача игровой информации, загрузка обновлений, контроль за читерами и т. д. Вторые предназначены для работы с данными — хэшированными (я надеюсь) паролями, количеством денег, идентификаторами предметов — в общем всем тем, что существует в игре и способно изменяться.
Системы хранения данных (Storage Area Network, SAN) — это тоже своего рода серверы, но предназначенные для надёжного хранения больших объёмов информации и быстрого доступа к ним. СХД обычно подключаются к серверам с помощью оптоволокна или другой высокоскоростной коммутации. На них обычно и хранятся базы данных и операционные системы с игровыми сервисами (тут возможны варианты).
Сетевое оборудование — это маршрутизаторы, свитчи, фаерволлы и прочие виды устройств, реализующие передачу данных между серверами и игроками. Видов сетевых топологий несколько, они сильно зависят от специфики конкретных инсталляций, ограничения по финансам и прочих вещей, поэтому я, с вашего позволения, расскажу только об одном частном случае, а именно — как это устроено в дата-центре, где хостится наш Eco-сервер.
Поскольку каждая минута простоя в игровой индустрии — это недовольные пользователи, а следовательно и потерянные деньги, к надёжности и отказоустойчивости там подходят со всей серьёзностью. В первом приближении это означает, что выход из строя любого узла не должен влиять на предоставление услуг совсем, либо время восстановления должно быть минимальным — секунды и минуты. Поэтому всё, что только можно на серьёзных хостингах дублируется — сетевое оборудование, серверы, системы хранения, интернет-каналы…
У нас это выглядит следующим образом — вся сетевая инфраструктура задублирована и в каждый сервер воткнуты кабели, идущие от разных сетевых устройств. Между собой эти устройства тоже подключены двумя «хвостами». Каждое хранилище данных подключено к серверам несколькими оптическими кабелями. Внутри серверов диски объединены в избыточные массивы, продолжающие работать даже в случае выхода отдельных дисков из строя, то же самое в СХД. Оперативная память в серверах не обычная, а с коррекцией ошибок, что позволяет избежать проблем в случае солнечных бурь и других электромагнитных флуктуаций. Серверы объединены в кластер, который способен быстро и без потери данных восстановить работу сервисов в случае выхода из строя одного или нескольких серверов. Звучит всё это довольно внушительно, но у крупных компаний, надо сказать, всё гораздо круче, хоть и стоит, как золотой паровоз.
Безусловно, в 2019 году компьютерная грамотность населения стала гораздо выше, чем, скажем, 20 лет назад, но я не побоюсь показаться скучным и расскажу про некоторые основы максимально популярным языком.
Для игры через интернет нужно ровно одно — сетевая связность между сервером и клиентом. Это, максимально утрируя — способность данных пройти от вашего компьютера через домашний роутер (если он есть) к оборудованию вашего провайдера, внутри его сети до стыка с другим провайдером, обычно более высокого уровня, внутри его сети до точки обмена трафиком, затем через оборудование магистрального провайдера — по оптоволокну за границу, может быть даже по дну океана… бла-бла-бла, вот несчастные данные и приехали в дата-центр какого-нибудь Близзарда. По дороге пакеты (отдельные куски данных) проходят несколько сетевых устройств и на каждом из них с ними может случиться что-то нехорошее. Самый простой случай — они просто потеряются и не дойдут до пункта назначения. Или дойдут, но уже не те. Нужно сказать, что интернет — система довольно устойчивая к неполадкам отдельных узлов, но это отнюдь не значит, что у вас не будет тормозить.
Для того, чтобы можно было подтвердить получение пакетов собеседником, сто лет назад был придуман протокол TCP. Несмотря на всю критику, высказываемую в его адрес — своё дело он выполняет неплохо, а именно — гарантирует, что все пакеты, отправленные вами, дойдут до получателя, причём в правильной последовательности, либо вы узнаете об обратном. Расплатой за эту надёжность является его крайняя неторопливость — данные должны несколько раз пройти туда-обратно, чтобы все убедились в корректности их получения.
Полной противоположностью является протокол UDP — никакого предваряющего передачу данных установления соединения, никаких подтверждений — только поток данных. UDP широко используется в случаях, когда скорость передачи пакетов важнее гарантированной доставки, правильной последовательности данных и отсутствия дублирования. Это, например, потоковое видео, голосовые звонки и, не поверите — компьютерные игры. В самом деле — намного важнее, чтобы сервер как можно скорее получил ваше нажатие на кнопку, чем уверенность в том, что вы сделали именно три шага влево, а не два или четыре. Обычно недостатки UDP разработчики игр пытаются скомпенсировать какими-то своими методами, чтобы, например, потери пакетов не приводили к ужасным последствиям.
Дело в том, что пинг для работы использует протокол, называемый ICMP — в рамках него передаются контрольные и сервисные сообщения, в том числе о наличии/отсутствии сетевой связности. Нюанс в том, что фактически для работы сервисов он не критичен и иногда правила его обработки существенно отличаются от TCP или UDP. Проще говоря — некоторые узлы могут не отвечать на пинги вовсе или делать это по остаточному принципу, если у них нет более важных дел. Со стороны клиента это может выглядеть как недоступность узла или потеря пакетов. С трассировкой возникает схожая проблема, потому что, например, в утилите tracert ОС Windows используется тот же ICMP. Кроме того, обе этих утилиты могут демонстрировать нерелевантные данные из-за так называемой несимметричной маршрутизации. В двух словах — это ситуация, при которой туда и обратно пакеты идут существенно различающимися путями, что со стороны клиента может выглядеть как «высокий пинг» или та же потеря пакетов. Самый простой способ избавиться от первого — проводить трассировку с использованием не tracert, а traceroute, который умеет работать с TCP/UDP и в нём можно указать конкретный номер порта (идеально — использовать тот же порт, что и игра).
Предположим, что с сетью у нас всё хорошо и пакеты радостно курсируют до сервера и обратно. Значит ли это, что можно облегчённо выдохнуть и наконец-то спокойно поиграть? Разумеется, нет — иначе зачем бы мне писать третий параграф? Проблемы сетевого характера могут возникать при низком пинге (а точнее — RTT, говорите грамотно) и отсутствии потерь пакетов. Имя этим проблемам — легион кривая архитектура сетевого взаимодействия. Рассмотрим очень животрепещущий для некоторой части ММОзговедов пример — в Eco при определённой скорости движения (а честно говоря — если вы хотя бы просто бежите по прямой) персонажа перестают успевать прогружаться текстуры под ногами и, в случае, если вы едете на автомобиле — он вместе с водителем падает непосредственно в ад, откуда его потом приходится доставать с бубном и плясками. В чём только не обвиняли наш несчастный сервер и меня лично, как его админа… а разгадка элементарна и описывается одним словом — геометрия. В самом деле, наверняка все (да, я оптимист) помнят ещё со средней школы формулу площади поверхности шара — 4πR2.
Что это означает на практике? Почти наверняка тайлы вокруг персонажа отрисовываются по концентрическим сферам, а это значит, например, что если на расстоянии 5 метров нужно отрисовать около 300 тайлов, то на расстоянии 10 — уже 1200, а на 20 — где-то 5000. Разумеется, если информацию обо всех этих тайлах передавать в реальном времени, да ещё хорошо, если не отдельно для каждого — никакой пропускной способности канала и мощности процессора не хватит. А в Эко, есть подозрения, что происходит именно так или как-то похоже. Как с этим справляются другие — вариантов много, но лично мне на ум первым приходит способ, при котором в момент захода в игровой мир пользователь сразу получает информацию обо всём или существенной части мира (с последующей фоновой подгрузкой оставшегося), а в дальнейшем от сервера к нему прилетают только изменения тайлов, коих относительно немного. Да, это сделает загрузку более долгой, но решит основную проблему.
На этой оптимистичной ноте я закругляюсь, благодарю за внимание и желаю стабильного интернета всем осилившим дочитать.