Правила форума


На этом форуме действует система премодерации сообщений для новых пользователей и система премодерации новых тем.

Взгляд изнутри: архитектура нового клиента LoL  
Автор Сообщение






Сервер: Черный Шрам
1
Сообщение Взгляд изнутри: архитектура нового клиента LoL

 

Привет! Меня зовут Эндрю Маквей, я архитектор программного обеспечения в Riot Games.

 

Сейчас мы находимся на последних стадиях переработки клиента League of Legends, рабочее название которого – "обновленный клиент LoL". В этой статье я опишу программную архитектуру обновления, назову причины некоторых изменений и расскажу об ограничениях, с которыми мы столкнулись, работая с текущим клиентом. Путешествие к финальной архитектуре было крайне захватывающим с технической точки зрения, и я рад поделиться с вами подробностями!

 

ЗАЧЕМ МЕНЯТЬ КЛИЕНТ?

 

Первая версия клиента, появившаяся в 2008 году, была создана на основе интерфейса Adobe AIR, которая использовала для обмена данными с нашими серверами сессионный сетевой протокол RTMP. Эта платформа служила нам верой и правдой: она предлагала богатую мультимедийную среду, позволявшую создать анимацию и эффекты, которые нельзя было реализовать в HTML того времени. Кроме того, она была кроссплатформенной и простой в освоении, что значительно упрощало работу команды, дающей указания художникам и дизайнерам.

 

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

 

ПРОБЛЕМА №1: HTML5 – СТАНДАРТИЗИРОВАННАЯ, ШИРОКО РАСПРОСТРАНЕННАЯ ПЛАТФОРМА

 

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

 

 

ПРОБЛЕМА №2: ИГРОКИ ХОТЯТ ОСТАВАТЬСЯ НА СВЯЗИ КАК В ИГРЕ, ТАК И ВНЕ ЕЕ

 

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

 

 

ПРОБЛЕМА №3: КОМАНДА РАЗРАБОТЧИКОВ RIOT ХОЧЕТ РАБОТАТЬ В ГАРМОНИИ

 

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

 

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

 

 

ШАГИ НАВСТРЕЧУ ПОТРЯСАЮЩЕЙ АРХИТЕКТУРЕ

 

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

 

Мы начали все с нуля и выбрали в качестве интерфейса Chromium Embedded Framework (CEF)Благодаря этому у нас в руках оказался мощнейший браузерный компонент, обладающий всеми преимуществами HTML5, который мы с легкостью могли изменять.

 

Сейчас вы узнаете, как мы пришли к нашей окончательной архитектуре.

 

ШАГ ПЕРВЫЙ: МИРОМ ПРАВИТ JAVASCRIPT!

 

Нашей первоначальной идеей было сделать все на JavaScript.

 

Приняв решение строить пользовательский интерфейс на HTML и JavaScript, мы захотели пойти дальше и реализовать на JavaScript еще и бизнес-логику и коммуникации, чтобы упростить и унифицировать архитектуру. (Подобное единообразие интерфейса и служб лежит в основе многих платформ – например, node.js)

 

Таким образом, мы создали на C++ простую библиотеку с минимумом функций, позволявшую JavaScript делать удаленные вызовы посредством протокола RTMP и обрабатывать асинхронные ответы. Мы решили не отказываться от RTMP, так как он прекрасно подходит для задач нашего уровня и потому что мы не хотели одновременно со сменой клиента менять коммуникационный протокол.

 

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

 

 

Что могло пойти не так при использовании столь прямолинейной технологии? Как оказалось, много чего.

 

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

 

Эта архитектура решила проблему №1, а вот перед проблемами №2 и №3 она оказалась бессильна. А еще, внутренний опрос разработчиков показал, что их продуктивность снизилась по сравнению с временами, когда они работали над AIR-клиентом. Упс.

 

ШАГ ВТОРОЙ: МЫ ЗАНОВО ОТКРЫЛИ ВЕБ-ПРИЛОЖЕНИЯ (СДЕЛАВ ИХ НАСТОЛЬНЫМИ)!

 

Нашим следующим шагом стала реализация микрослужб на C++. Целью было представить асинхронный игровой протокол в виде набора REST-ресурсов.

 

Мы начали думать, из чего состоят обычные веб-приложения, и поняли, что нам не хватает промежуточного звена. И тогда мы создали слой микрослужб (который по-прежнему работал на компьютере игрока), представленных протокол RTMP в виде REST-ресурсов. Это было сделано, чтобы избавиться от излишней асинхронности в JavaScript. Чтобы обрабатывать события в пользовательском интерфейсе, мы использовали технологию WebSockets. Слой микрослужб получил название "фундамент".

 

 

Ниже изображен Swagger UI с ресурсами фундамента, отвечающими за обновление клиента. Эта конструкция сильно упростила код JavaScript, позволив использовать стандартные методы веб-разработки.

 

 

У этой архитектуры есть еще одно преимущество: при сворачивании клиента интерфейс CEF (и виртуальные машины JavaScript) перестает использоваться – работает лишь фундамент. Это возможно благодаря тому, что фундамент хранит исходное состояние – весь пользовательский интерфейс можно воссоздать с помощью GET-запросов. Фундамент занимает в памяти всего около 20 МБ, что примерно равняется размеру нескольких картинок с котиками из интернета. Отныне никому не нужно будет закрывать клиент после попадания в игру (как делают некоторые игроки, чтобы освободить память).

 

Это позволило нам еще ближе продвинуться к созданию "всегда доступного" клиента, что решало проблему №2. Фундамент может показывать сообщения (приглашения в игру или предложения дружбы) в области уведомлений, даже работая в фоновом режиме.

 

ШАГ ТРЕТИЙ: ОПЯТЬ НА ТЕ ЖЕ ГРАБЛИ...

 

Следующим шагом необходимо было сделать архитектуру расширяемой.

 

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

 

Чтобы было понятнее, насколько важна расширяемость, я использую аналогию. Представьте, что десятерых писателей попросили написать одну книгу. Предположим, что над каждой главой они будут работать вместе (например, все они будут писать вторую главу под названием "LoL для новичков"). И это будет ужасно, ведь каждый из них будет менять предложения, написанные другим. Разумнее было бы поручить каждому писателю писать свою главу (например, один пишет пятую главу, "Таланты", а второй – шестую, "Руны"), позволив им работать независимо друг от друга. Разумеется, при этом нельзя забывать о том, что главы должны быть связаны между собой.

 

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

 

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

 

Таким образом, пользовательский интерфейс вместе с сопутствующим функционалом вошел в плагин front-end (FE), а коммуникационная логика C++ (хоть это и не самое точное название) – в плагин back-end (BE). И заметьте, оба типа плагинов уживаются друг с другом в обновленном клиенте LoL – мы используем термины "front-end" и "back-end" только потому, что архитектура имитирует типичную связку клиент-сервер, даже если при этом она входит в состав одного-единственного настольного приложения.

 

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

 

 

В процессе перехода на новую архитектуру нам пришлось распотрошить монолитный уровень данных JavaScript. Мы использовали ember-orbit, чтобы поддерживать единый связный граф объектов, представляющих наши ресурсы REST. И это было одним из главных источников головной боли – разные команды получали доступ к данным друг друга с помощью объектных ссылок, а не служебных вызовов. Такой уровень совместной работы нам был явно не нужен.

 

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

 

ШАГ ЧЕТВЕРТЫЙ: СПРОСИТЕ N РАЗРАБОТЧИКОВ НА JAVASCRIPT ОБ ИХ ЛЮБИМОМ MVC-ФРЕЙМВОРКЕ, И ПОЛУЧИТЕ N+1 ОТВЕТОВ.

 

Мы позволили каждой команде выбрать свой фреймворк JavaScript.

 

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

 

Тем не менее у нас возникла проблема. Некоторым командам не нравился Ember.js, и они хотели использовать веб-компоненты напрямую. У других команд были написаны свои собственные веб-приложения, использующие другие фреймворки, и они хотели внедрить их в новый клиент.

 

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

 

Поворотный момент наступил, когда мы поняли, что в такой огромной компании, как Riot, невозможно заставить всех разработчиков использовать даже одну и ту же версию Ember. Это стоило нам немалых трудов, но в итоге мы изменили архитектуру клиента таким образом, чтобы каждый из плагинов мог использовать свой собственный фреймворк – фреймворки JavaScript стали привязаны к плагинам front-end.

 

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

 

ИТОГОВАЯ АРХИТЕКТУРА

 

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

 

Мы вновь провели опрос разработчиков и обнаружили, что продуктивность увеличилась на 15% и эта цифра быстро растет. Отлично!

 

 

Один из разработчиков сказал, что мы создали "настольный банк данных". Я же считаю, что новый клиент очень похож на Atom – расширяемый текстовый редактор от Github, основанный на CEF и созданный с помощью фреймворка Electron. В самом начале работы я и подумать не мог, что все закончится именно этим.

 

В этой статье за скобками осталось множество вопросов – например, как мы добиваемся бесшовного, плавного взаимодействия разных функций, как создавались качественные эффекты на одном лишь HTML5 и как происходит независимое развертывание разных возможностей. Эти области интересны сами по себе, и мы будем рады рассказать о них подробно, если вам будет интересно. Ждем ваших комментариев!



30 май 2016, 23:14
Профиль

0
Сообщение Взгляд изнутри: архитектура нового клиента LoL

А в двух словах то что? А то сложно, сложно, ничего не понятно



30 май 2016, 23:40
Профиль

0
Сообщение Взгляд изнутри: архитектура нового клиента LoL

centrovoy писал(а):

А в двух словах то что? А то сложно, сложно, ничего не понятно

Современные технологии. Клиент производительней и лучше overall. 



31 май 2016, 00:08
Профиль

0
Сообщение Взгляд изнутри: архитектура нового клиента LoL

Такая сложная система а денаи добавить не додумались.



31 май 2016, 00:17
Профиль

0
Сообщение Взгляд изнутри: архитектура нового клиента LoL

Suslik писал(а):

Такая сложная система а денаи добавить не додумались.

И скрытый пул.Oh,wait...



31 май 2016, 01:21
Профиль

0
Сообщение Взгляд изнутри: архитектура нового клиента LoL

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

 

 



31 май 2016, 09:35
Профиль

0
Сообщение Взгляд изнутри: архитектура нового клиента LoL

Marshall писал(а):

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

 

 

Игровой движок их собственный.



31 май 2016, 10:20
Профиль

0
Сообщение Взгляд изнутри: архитектура нового клиента LoL

Я так понимаю, подобные заумные объяснения нужны для того, что если ничего не измениться и клиент останется нестабильным, лагающим, жрущим ресурсы дерьмом, то они смогут оправдаться тем, что "ну вот мы же вам показывали, как все сложно было. Неужели вы не поняли сразу?"...



31 май 2016, 11:21
Профиль

0
Сообщение Взгляд изнутри: архитектура нового клиента LoL

вау, до них наконец дошло, что на с++ или с# с применением простейшего йаваскрипта клиент быстрее, стабильнее и проще в разработке, чем на ссаном эире и самописном и кривом парсере скриптов? вау. всего лишь 2 года понадобилось.



01 июн 2016, 00:02
Профиль

0
Сообщение Взгляд изнутри: архитектура нового клиента LoL

Там глядишь через 2 года снова солоку введут.



01 июн 2016, 07:11
Профиль
Начать новую тему Ответить на тему


Перейти:  

На сайте использованы материалы, принадлежащие Blizzard Entertainment. Копирование материалов возможно только c разрешения портала. В противном случае это будет называться уже другим словом.
Рейтинг@Mail.ru