Введение
По предыдущим статьям я полагаю, что у всех есть определенное представление об эволюции архитектуры фронтенда официального сайта торгового центра vivo: от неуклонного продвижения разделения фронтенда и бэкенда к мульти- заканчивая исследование и практику небольших программ, команда продолжает вводить новшества и пробовать.
В этой статье давайте поделимся практическим опытом официального веб-сайта vivo mall в Node Server Side Rendering (SSR). В этой статье основное внимание уделяется следующим аспектам:
- Сравнение КСО и БСО
- оптимизация производительности
- Автоматическое развертывание
- Катастрофа, даунгрейд
- журнал, монитор
2. Фон
Официальный веб-сайт vivo в настоящее время принимает одностраничный режим SPA для разделения внешнего и внутреннего интерфейса. SPA будет упаковывать весь JS в целом. Проблема, которую нельзя игнорировать, заключается в том, что файл слишком большой, что приводит к длительному ожиданию перед рендерингом. Особенно, когда скорость сети низкая, пользователям неудобно ждать окончания белого экрана. Поэтому команда фронтенда официального сайта vivo попыталась внедрить технологию SSR, чтобы ускорить скорость доступа к первому экрану страницы, тем самым улучшив взаимодействие с пользователем.
3. Введение в ССР
3.1 Что такое ССР?
Рендеринг страницы в основном делится на рендеринг на стороне клиента и рендеринг на стороне сервера:
- Рендеринг на стороне клиента (CSR)
Сервер возвращает только базовый html-шаблон, браузер загружает js в соответствии с html-содержимым, получает данные и отображает содержимое страницы;
- Рендеринг на стороне сервера (SSR)
Содержимое страницы обрабатывается на сервере и возвращается в браузер для прямого отображения.
3.2 Зачем использовать SSR?
По сравнению с традиционным SPA (одностраничным приложением) преимущества SSR в основном заключаются в следующем:
- Лучшая поисковая оптимизация (SEO), SPA-приложение сначала отображает загрузочную диаграмму-хризантему, а затем получает контент через Ajax, а поисковая система не ждет асинхронного завершения, прежде чем сканировать содержимое страницы;
- Более быстрое время до контента, особенно для медленных сетевых условий или медленных устройств, нет необходимости ждать загрузки и выполнения всего кода JavaScript перед отображением разметки, отображаемой сервером. Пользователи могут быстрее увидеть полностью обработанную страницу и улучшить взаимодействие с пользователем. Следующий рисунок может более наглядно отразить эффект загрузки.
Сравнение рендеринга страниц CSR и SSR:
4. Практика ССР
Технологический стек проекта торгового центра официального веб-сайта vivo — Vue.Учитывая, что создать набор приложений для рендеринга на стороне сервера с нуля сложнее, я выбрал официальную рекомендацию Vue.Nuxt.jsФреймворк, представляющий собой фреймворк более высокого уровня, основанный на экосистеме Vue, обеспечивает чрезвычайно удобный опыт разработки серверных приложений Vue.
Здесь не рассказывается об основных способах использования. Заинтересованные учащиеся могут перейти наОфициальный сайт Nuxt.jsИзучите основы использования; мы в основном фокусируемся на некоторых основных проблемах, возникающих в процессе практики:
- Производительность: как оптимизировать производительность, улучшить QPS и сэкономить ресурсы сервера?
- Аварийное восстановление: как справиться с аварийным восстановлением и реализовать автоматический переход на более раннюю версию?
- Журналы: как получить доступ к журналам для облегчения выявления проблем?
- Мониторинг: как отслеживать службы Node?
- Развертывание: Как пройти через процессы CI/CD компании, автоматизировать развертывание?
4.1 Оптимизация производительности
Несмотря на то, что скорость рендеринга Vue SSR очень высока, из-за накладных расходов на создание экземпляров компонентов и виртуальных узлов DOM производительность механизма шаблонов, основанного на сращивании строк, сильно отличается. Это влияет на взаимодействие с пользователем, поэтому необходима оптимизация производительности.
4.1.1 Сценарий 1 Включить кэширование
а, кеш страницы:Используйте при создании экземпляра рендераLRU-CacheДля кэширования отображаемого html, когда есть другой запрос на доступ к странице, строка html в кеше возвращается напрямую.
nuxt.config.js добавляет конфигурацию:
serverMiddleware: ["~/serverMiddleware/pageCache.js"]
Создайте serverMiddleware/pageCache.js в корневом каталоге
б. Кэш компонентов:Сохраняйте визуализированный DOM компонента в кеше, регулярно обновляйте его и извлекайте DOM из кеша в течение срока действия. В основном подходит для повторно используемых компонентов, в основном используемых для списков, таких как списки продуктов.
Файл конфигурации nuxt.config.js:
const LRU = require('lru-cache')
module.exports = {
render: {
bundleRenderer: {
cache: LRU({
max: 1000, // 最大的缓存个数
maxAge: 1000 * 60 * 5 // 缓存5分钟
})
}
}
}
Компонент кэша добавляет name и serverCacheKey в качестве уникальных значений ключа:
export default {
name: 'productList',
props: ['productId'],
serverCacheKey: props => props.productId
}
C. Кэш API:Сервер Node должен сначала вызвать фоновый интерфейс для получения данных перед рендерингом.Скорость получения интерфейса напрямую влияет на время рендеринга.Кэш интерфейса может ускорить скорость обработки каждого запроса и быстрее выпустить запрос.Тем самым повышение производительности. API-кеширование в основном подходит для интерфейсов, где данные в основном остаются неизменными, изменения происходят не очень часто и не имеют ничего общего с личными данными пользователя.
4.1.2 Схема 2 параллельных запросов интерфейса
Для одной и той же страницы несколько интерфейсов могут быть вызваны одновременно на уровне узла.Если это последовательный вызов, время ожидания будет больше.Если это параллельный запрос, время ожидания будет сокращено.
Например:
let data1 = await $axios.get('接口1')
let data2 = await $axios.get('接口2')
let data3 = await $axios.get('接口3')
Можно изменить на:
let {data1,data2,data3} = await Promise.all([
$axios.get('接口1'),
$axios.get('接口2'),
$axios.get('接口3')
])
4.1.3 Вариант 3: свернуть первый экран
Основное влияние на пользовательский опыт оказывает время белого экрана первого экрана, в то время как второй экран, третий экран... не нужно отображать сразу. В качестве примера возьмем страницу сведений о продукте, как показано ниже:
Структура страницы может быть разделена, первые элементы экрана используют SSR, а не складывающиеся элементы экрана используют CSR; данные SSR необходимо получить с помощью метода asyncData, а данные CSR можно получить в mount.
CSR записывается следующим образом:
<client-only>
客户端渲染dom
</client-only>
4.1.4 Схема 4 На некоторых страницах используется CSR
Не все страницы имеют высокие требования к опыту и SEO.Для бизнеса, такого как торговый центр, вы можете выполнять SSR только для основных страниц, таких как домашняя страница и страница сведений о продукте, что может значительно снизить нагрузку на сервер.
4.1.5 Сравнение стресс-теста производительности до и после оптимизации
До оптимизации:
Оптимизировано:
Как видно из приведенного выше рисунка, QPS до оптимизации составляет всего 125, а после серии оптимизаций QPS достигает 6000, то есть увеличение почти в 50 раз.
Понижение здесь относится к понижению SSR до CSR и использованию Node в качестве SSR, узким местом является ЦП и память. Если сервер Node зависнет, это напрямую приведет к тому, что страница недоступна. Поэтому, чтобы обеспечить бесперебойную работу проекта после выхода в онлайн, необходимо предусмотреть решения для аварийного восстановления и даунгрейда.
Nuxt.js может поддерживать как CSR, так и SSR. При упаковке мы создаем пакеты SSR и CSR и развертываем их отдельно.
В проекте используются следующие сценарии понижения версии:
4.2 Стратегия понижения рейтинга
4.2.1 Деградация системы мониторинга
Запустите службу на сервере Node, чтобы контролировать использование ЦП и памяти процессом Node, и установите пороговое значение.При достижении порогового значения SSR останавливается, а файл записи CSR index.html напрямую возвращается для перехода на более раннюю версию.
4.2.2 Стратегия понижения версии Nginx
4.2.2.1 Понижение всей платформы
Например, во время больших акций, таких как 618 и Double 11, мы заранее знаем, что трафик будет очень большим, мы можем заранее изменить конфигурацию Nginx, перенаправить запрос на статический сервер, вернуть index.html и переключиться к КСО.
4.2.2.2 Понижение версии единого доступа
Когда случайный сервер Node возвращает код ошибки 5xx или сервер Node напрямую зависает, мы можем автоматически переключиться на CSR с помощью следующей конфигурации Nginx, чтобы обеспечить нормальный доступ для пользователей.
Nginx настроен следующим образом:
location / {
proxy_pass Node服务器地址;
proxy_intercept_errors on;
error_page 408 500 501 502 503 504 =200 @spa_page;
}
location @spa_page {
rewrite ^/* /spa/200.html break;
proxy_pass 静态服务器;
}
4.2.2.3 Укажите метод рендеринга
Добавьте параметр isCsr=true в url, и слой Nginx перехватит параметр isCsr.Если этот параметр включен, он указывает на CSR, иначе он указывает на SSR, таким образом, страница может быть пропущена через url настройка параметров, снижающая нагрузку на сервер Node.
4.3 Автоматическое развертывание CI/CD
На основе CI/CD компании мы внедрили два автоматизированных решения для развертывания: развертывание Docker и развертывание сценария Shell.
4.3.1 Схема 1 Создание и развертывание сценария оболочки
Для метода сценария оболочки наша основная проблема заключается в том, как установить указанную версию Node через скрипт, Здесь мы можем разделить его на два этапа:
1、安装nvm, nvm 是Node.js 的版本管理器(version manager)
2、通过nvm安装或者切换成对于的Node版本
# 定义安装nvm的方法
install_nvm() {
echo "env $app_env install nvm ..."
wget --header='Authorization:Basic dml2b2Rldm9wczp4TFFidmtMbW9ZKn4x' -nv -P .nvm http://xxx/download/nvm-master.zip
unzip -qo .nvm/nvm-master.zip
mv nvm-master/* $NVM_DIR
rm -rf .nvm
rm -rf nvm-master
. "$NVM_DIR/nvm.sh"
if [[ $? = 1 ]];
then
echo "install nvm fail"
else
echo "install nvm success"
fi
}
# 定义安装Node的方法
install_node() {
# command_args为用户自定义的Node版本号
local USE_NODEVER=$command_args
echo "will install NodeJs $USE_NODEVER"
nvm install $USE_NODEVER >/dev/null
echo "success change to NodeJs version" $(node -v)
}
# Node环境安装
prepare() {
if [[ -s "$NVM_DIR/nvm.sh" ]];
then
. "$NVM_DIR/nvm.sh"
else
install_nvm
fi
echo "nvm version $(nvm --version)"
install_node
}
4.3.2 Вариант 2. Сборка и развертывание Docker
Docker — это механизм контейнера приложений с открытым исходным кодом, который позволяет разработчикам упаковывать свои приложения и зависимости в переносимый образ, который затем можно распространять на любую популярную машину Linux или Windows, а также можно виртуализировать. Контейнеры полностью изолированы и не имеют никакого интерфейса друг с другом.
# 基础镜像
FROM node:12.16.0
# 创建文件存放目录
RUN mkdir -p /home/docker-demo
WORKDIR /home/docker-demo
COPY . /home/docker-demo
# 安装依赖
RUN yarn install
# 打包,并把静态资源进行md5压缩
RUN yarn prod
# 静态资源部署CDN
RUN yarn deploy
# 端口号
EXPOSE 3000
# 项目启动命令
CMD npm start
Для сравнения, развертывание Docker имеет большие преимущества:
- Проще построить и развернуть
- Согласованная операционная среда «Этот код не проблема на моей машине».
- Эластичное масштабирование
- Более эффективное использование системных ресурсов
- быстро - операции управления (запуск, остановка, запуск, перезапуск и т. д.) выполняются в секундах или миллисекундах
4.4 Мониторинг и сигнализация
Мониторинг является очень важной частью всего жизненного цикла продукта, он обеспечивает раннее предупреждение и своевременное обнаружение неисправностей заранее, а также предоставляет подробные данные после события для отслеживания и локализации проблем.
В случае сбоя приложения требуется подходящая цепочка инструментов для поддержки обнаружения и устранения проблемы.Мы представили решение для мониторинга производительности приложений Node.js корпоративного уровня с открытым исходным кодом и онлайн-решение для обнаружения сбоев Easy-Monitor, которое может лучше отслеживать Node. .js.js для решения проблем с производительностью и стабильностью. Мы развернули эту систему во внутренней сети и выполнили вторичную разработку, интегрировали вход в домен внутренней сети и можем передавать информацию о тревогах через внутренний инструмент чата.
4.5 Журналы
After applying on-line, once an exception occurs, the first thing is to find out what happened at that time, such as when the user how to operate, how to respond and other data, the log information will give us a first-hand Информация.因此我们需要接入公司的日志系统。
4.5.1 Реализация
Компонент лога упакован на основе log4js и подключен к лог-центру компании
Добавьте в nuxt.config.js:
export default {
// ...
modules: [
"@vivo/nuxt-vivo-logger"
],
vivoLog: {
logPath:process.env.NODE_ENV === "dev"?"./logs":"/data/logs/",
logName:'aa.log'
}
}
4.5.2 Использование
async asyncData({ $axios,$vivoLog }) {
try {
const resData = await $axios.$get('/api/aaa')
if (process.server) $vivoLog.info(resData)
} catch (e) {
if (process.server) $vivoLog.error(e)
}
},
4.5.3 Результаты
5. Пишите в конце
Улучшение пользовательского опыта является постоянной темой.Внешняя команда торгового центра официального веб-сайта vivo стремится к постоянным инновациям в технологиях, надеясь повысить качество обслуживания пользователей за счет технологических исследований. -end команда официального веб-сайта vivo по технологии SSR Я хочу поделиться своим опытом и надеюсь узнать и обсудить с вами.
Автор: фронтенд-команда официального сайта vivo mall