Приветствую всех вСообщество облачных технологий Tencent, получить больше крупной технической практики Tencent по галантерее ~
автор:Ван Бинь
задний план
С 2014 года в проекте Interest Tribe всегда используется режим рендеринга фронтенда, этот режим заключается в том, что html страницы представляет собой пустую оболочку, а содержимое первого экрана нужно подгружать после загрузки и css, и js, а cgi запрашивается для получения данных перед рендерингом для пользователей. Преимущество этого режима заключается в том, что работа с серверной частью и интерфейсом может быть полностью разделена, что значительно упрощает ежедневную разработку и обслуживание.
В текущем режиме работы, чтобы максимально сократить время работы первого экрана, мы сделали много оптимизаций, в том числе использовали механизм офлайн-пакетов для сокращения времени работы css и js.
Однако все эти оптимизации по-прежнему основаны на выполнении JS перед доставкой пользователю первого экрана.Если вы столкнетесь с машиной, которая очень медленно выполняет JS на Android, это все равно займет много времени.
С прямыми страницами html больше не просто пустая оболочка, а хорошо отрисованная страница, так что пользователи могут видеть контент, не дожидаясь загрузки и выполнения JS, что значительно снижает беспокойство пользователя.
В существующем рабочем режиме использование средств изоморфной прямой может не только сохранить наш существующий режим разработки, но и значительно снизить рабочую нагрузку. Вы только представьте, сколько работы нам придется перестроить, если мы перевернем все существующие рабочие режимы и воспользуемся обычным прямотоком.
Изоморфные прямолинейно, передняя и задняя части используют один и тот же набор кода, логика рендеринга переднего плана переносится на сервер для завершения, а результаты рендеринга передаются пользователю.Благодаря системе React мы применили такие возможности, чтобы заинтересовать проект Tribal.
курс
Прежде всего, давайте попробуем полную сумму на небольшой странице и постоянно решаем и отрегулируйте проблемы, встречающиеся во время процесса.
Во-первых, после того, как наша архитектура созреет, мы используем эту систему для трех основных интересов на странице сведений о племенной странице.
После непрерывной работы в градациях серого и решения проблем изоморфизм последней страницы сведений о посте был официально запущен в полном объеме.
Почти все машины являются виртуальными машинами v4.
Эффект
Интуитивно почувствуйте эффект сравнения, как показано ниже
Интерфейсный рендеринг слева, изоморфный прямой справа
Хорошо видно, что эффект оптимизации, вызванный прямым выходом под модель Android, очень очевиден.В то же время, по данным измерения нормальной скорости, время, проведенное на первом экране прямого выхода, уменьшается на 50%, и доля медленных пользователей снижается на 3 процентных пункта
Архитектура
Архитектура внешнего кода традиционно представляет собой систему архитектуры react+redux Использование архитектуры redux может сделать наш прямой вывод более контролируемым.
испытание
проблема с памятью
В большинстве случаев с такими проблемами сталкивается изоморфизм: обычные front-end страницы редко учитывают причину утечек памяти, но код, работающий на стороне узла, должен учитывать проблему утечек памяти.
В конвейере, к которому обращается пользователь, вызов res.end() завершается.Теоретически память, сгенерированная конвейером, может быть полностью высвобождена.Если ее нельзя высвободить, возникнет проблема роста памяти.
Мы все знаем, что переменные, связанные с GC ROOT, не могут быть переработаны, слишком много неконтролируемых кодов фронтенда приведет к утечкам памяти, нам нужно общее решение.
Исходный код
let Main = require(MainEntry);
Хотя каждому запросу и каждому пользователю потребуется изоморфный компонент Main, поскольку требование на стороне узла является одноэлементным режимом, Main, на который ссылается каждый пользователь, является одной и той же ссылкой, и каждый запрос относится к Main (выполнение Main). объявление переменной, если переменная подключена к цепочке ссылок Main, не может быть освобождена, когда запрос пользователя заканчивается, потому что ссылка Main является синглтоном и будет кэшироваться узлом, поэтому эти переменные не могут быть переработаны, будет серьезная память проблемы с утечкой.
Проблема резкого увеличения памяти при выходе в интернет
Чтобы решить эту проблему, можно создать новый экземпляр Main для каждого пользовательского запроса, так что, когда пользовательский запрос завершится, ссылка на Main может быть восстановлена плавно, и не будет проблемы с утечкой памяти.
В настоящее время племя использует решение vm, которое создает среду песочницы для каждого запроса пользователя.
if(! mainVmScriptCache[entry]){
var code = fs.readFileSync(require.resolve(entry), 'utf8');
mainVmScriptCache[entry] = new vm.Script(m.wrap(code), {
filename: entry
});
}
//var startVmTime = + new Date();
var module = {
exports: {}
};
var exports = module.exports;
mainVmScriptCache[entry].runInThisContext()(exports, require, module, __filename, __dirname);
Main = exports.default;
Каждый раз, когда пользователь запрашивает, Main будет перекомпилироваться. Эта ссылка Main не будет использоваться совместно с другими запросами. После завершения запроса Main также будет переработан, и весь мусор, созданный в Main, будет переработан вместе.
Память эффективно контролируется
Что касается проблем с производительностью, производительность, генерируемая виртуальной машиной, увеличит время использования ЦП примерно на 20 мс, но это очень эффективно для управления памятью.
Что касается оптимизации этой части, то изоморфная прямолинейность изначально является задачей, интенсивно использующей ЦП, но позже ее можно комбинировать с кешем для преобразования задач, интенсивно использующих ЦП, в задачи, интенсивно использующие память.
Вторичная компьютерная графика
Хотя решение этой проблемы не сложно, важно то, что мы можем найти эту часто упускаемую из виду проблему до того, как страница сведений будет увеличена.
Для общего рефакторинга прямого решения код для внешнего интерфейса будет выполняться в обычном режиме, так что cgi будет снова отправлен на внешний интерфейс, а данные станут самыми последними. Однако на самом деле сервер уже отправил запрос пользователю, из-за чего пользователь дважды запросил cgi.
Схему здесь обычно можно рассматривать с точки зрения оптимизации.
Когда запустили первую маленькую страницу, мы не особо обратили внимание на эту проблему, но когда запустили страницу деталей в градациях серого, постепенно поняли, что это не проблема оптимизации, а серьезная архитектурная проблема. Если страница с подробностями будет напрямую подключена к сети, влияние на фоновую компьютерную графику будет очень большим: первоначальные 300 миллионов ежедневных посещений внезапно превратятся в 600 миллионов посещений, что намного больше, чем давление на фон с 30 до 60 млн. Поэтому эту проблему необходимо решить, прежде чем продолжать увеличивать объем.
Решение состоит в том, чтобы использовать кэш данных, чтобы выплавить данные, запрашиваемые узлом на передний конец одновременно, так что перехват выполняется, когда передние конечные запросы проверяют, есть ли кэш данных, и если это так, нет CGI запрашивается, что может значительно улучшить производительность. Устранить количество добавленных CGI.
Однако проблема заключается в том, что когда данные хранятся с параметром url_ в качестве ключа, кэш не может быть сопоставлен из-за несогласованных параметров между интерфейсом и сервером.Например, интерфейс использует параметр информации о географическом местоположении. , которые нельзя обменять на стороне сервера. Решение состоит в том, чтобы хранить эти параметры в файле cookie, а сторона узла может использовать данные о местоположении, кэшированные файлом cookie, при запросе.
(Клиент полагается на параметры для использования файлов cookie, и частота попаданий в кэш значительно улучшается)
автономный пакет
Конечно, использование офлайн-пакетов для ресурсов css и js — это само собой разумеющееся, но в племени также сложно получить доступ к офлайн-пакетам.
(Есть много значений js, css md5)
На стороне клиента существует множество версий офлайн-пакетов, и каждая версия офлайн-пакета имеет разные md5 для отсутствующих ресурсов.Как узнать, какой md5 локального автономного пакета пользователя предназначен для ресурсов, на которые ссылается прямая страница?
Мы использовали следующее решение:
При компиляции офлайн-пакета на фронтенде в html будет внедряться скрипт, функция скрипта - подкладывать следующие данные (версию) представляющие номер версии под текущую страницу, и при этом называть html как [версия].html и отправить его на сервер, прямой исходящий запрос, отправленный автономным пакетом, будет содержать эту информацию о версии. В соответствии с этой информацией о версии мы будем использовать [версия].html в качестве шаблона для страница, которую нужно выплюнуть на этот раз, чтобы клиентские ресурсы могли быть сопоставлены с оффлайн-пакетом пользователя.
Приоритет в верхней части страницы
Приоритет первого экрана также является проблемой, которая часто игнорируется всеми.
<html>
<head>
<link href="main.css" />
</head>
<body>
<div class="root"></div>
<script src="lib.js"></script>
<script src="render.js"></script>
</body>
</html>
Если вы используете прямо, это будет выглядеть так
<html>
<head>
<link href="main.css" />
</head>
<body>
<div class="root">
<h1>title</h1>
<div class="content">content</div>
</div>
<script src="lib.js"></script>
<script src="render.js"></script>
</body>
</html>
Вроде не проблема, контент появляется прямо в .root
Но мы часто упускаем из виду проблему опыта: действительно ли такая страница быстрее, чем непрямая?
Ответ 80% нет! Дело не в том, что большинство случаев не быстрее, чем непрямые! Даже опыт будет медленнее, чем непрямой!
Причина в том, чтобы выяснить, когда появится первый экран браузера. Когда браузер выполнит первую отрисовку? Проще говоря, в большинстве случаев элементы DOM, которые являются прямыми, не будут отображаться в первый раз, но будут дождитесь рендеринга. Содержимое первого экрана будет отображаться только после выполнения .js. Если render.js загружается и выполняется, то в чем смысл элемента DOM, который мы напрямую выводим? Это возвращает к нормальному внешнему интерфейсу рендеринг, и пустая оболочка больше, чем оригинал.Есть больше, поэтому неизбежно, что время белого экрана будет больше.
Итак, чтобы решить эту проблему, нам нужно, чтобы узлы DOM, которые выходят, могли отображаться в первый раз.Решение не сложно.Мы можем использовать ленивую загрузку.Племя использует лучшее асинхронное решение для отображения содержимого первый экран в первый раз Загрузите JS за один раз, не блокируя рендеринг DOM или доставку первого экрана.
Благодаря руководству weetli, одноклассника по ядру x5.
О времени рендеринга первого экрана:
- CSS будет блокировать рендеринг (рисование) (css не загружается и полный рендеринг не имеет смысла)
- js будет блокировать синтаксический анализ документа, а не рендеринг
- Когда браузер анализирует тег script, если ресурс js готов, он сначала выполнит js, а затем отобразит его, если он не выполнен, он отобразит первым.
- Большинство онлайн-ресурсов cdn сильно кэшированы или имеют мобильные офлайн-пакеты QQ.Когда браузер анализирует тег скрипта, ресурс js готов, и сначала будет выполнен js, а затем будет выполнен рендеринг.
Время рендеринга первого экрана зависит от многих факторов и очень неконтролируемо, но браузер ядра x5 предоставляет удобный метод управления для оптимизации времени первого экрана.
Время рендеринга первого экрана х5 можно определить самостоятельно, добавив метатеги
<meta name="x5-pagetype" content="optpage">
x5-pagetype имеет три необязательных типа
- автоматическое обнаружение верхней части сгиба по умолчанию
- optpage над ярлыком сгиба
- Веб-приложение не обнаруживает
Над сгибом находится этикетка
<first-screen/>
Поддерживать стабильность
Самой большой проблемой фоновой онлайн-задачи является стабильность и устойчивость к сбоям.Во-первых, задача обеспечивает стабильность службы пользователя.При возникновении некоторых неожиданных проблем онлайн-страница может по-прежнему стабильно предоставлять услуги.
По сравнению с традиционным прямым выходом, изоморфный вариант имеет более сильные возможности аварийного восстановления, что также является преимуществом изоморфного прямого выхода! Поскольку все еще существуют внешние страницы рендеринга, которые могут предоставлять обычные услуги, когда изоморфный прямой выход не работает, есть два режима страниц развертывания племени.
Существующие пути рендеринга интерфейса:Tribe.QQ.com/Mobile/He…
Соответствующий прямой путь к странице:Племя.QQ.com/Mobile/V2/…
Например, эта прямая страницаПлемя.QQ.com/Mobile/V2/…(Симулятор открыт), удаление v2 не прямо со страницыTribe.QQ.com/Mobile/He…(эмулятор открывается)
Проект Interest Tribe Direct предлагает двухуровневую стратегию аварийного восстановления с точки зрения стратегии аварийного восстановления.
Первый слой Framework Layer Timeout, устойчивость к ошибкам
Когда фреймворк истечет или произойдет ошибка, он вернет исходную непрямую html-страницу страницы, чтобы пользователь мог перейти к обычному внешнему рендерингу.
Второй уровень Уровень эксплуатации и обслуживания Отказоустойчивость обслуживания во время простоя
Отказоустойчивость этого уровня будет размещена на внешнем уровне сервера.Проще говоря, если при запросе прямой страницы возникает ошибка 5xx или 4xx, она неявно перенаправляет путь к не- прямая страница без v2.
location ^~ /mobile/v2/ {
proxy_pass xxx;
proxy_intercept_errors on;
error_page 403 404 408 500 501 502 503 504 @buluo_static_page;
}
location @buluo_static_page {
rewrite /v2/(.*)$ /mobile/$1 last;
}
Даже если вся служба прямого выхода полностью отключена, нам не нужно беспокоиться о доступности службы.
автоматизированный тест
Другой уровень, как обеспечить стабильность обычного процесса разработки, также является важной частью всей системы архитектуры.Не ждите, пока проблемный код будет отправлен онлайн, чтобы узнать, что проблема есть.
В систему разработки и сопровождения прямолинейки племя впервые внедрило решение автоматизированного тестирования + git hook, чтобы гарантировать, что представленный код не пойдет не так.
Когда код, отправленный другими учащимися, будет отправлен, сработает локальный препуш-хук, и автоматический тест будет выполнен прямо со страницы.Только через автоматический тест можно отправить код.
Это решение в значительной степени гарантирует стабильность прямого исходящего сервиса.С момента запуска этого решения не было никаких проблем с прямым исходящим сервисом~
Перспектива
Сложность прикладных технологий заключается не в преодолении технических проблем (поскольку у большинства проблем есть решения), а в способности непрерывно комбинировать собственный опыт работы с продуктом, обнаруживать существующие проблемы опыта и продолжать использовать лучшие технические решения для решения проблем. пользовательский опыт и внести свой вклад в разработку всего продукта.
Как крупнейшая изоморфная практика прямого обслуживания компании, мы будем дополнительно оптимизировать взаимодействие с пользователем в последующем плане. Например, использование серверного кеша и других средств для дальнейшего сокращения времени, затрачиваемого на стороне сервера, оптимизации процесса загрузки простых изображений и т. д. В то же время мы поделимся с вами более богатым практическим опытом.
Связанное Чтение
Интерфейсная технология связи в реальном времени WebRTC
Взгляд с высоты птичьего полета на фронтенд, а потом на оптимизацию производительности
Эта статья была разрешена автором для публикации в сообществе Tencent Cloud Technology Community, укажите это при перепечатке.Источник статьи
Оригинальная ссылка: https://cloud.tencent.com/community/article/531340