Все мы знаем что nuxt.js 2 (да и любое node.js приложение с SSR) не держит нагрузку без кеша, в среднем проекте если включить режим SSR то будет держать 20-30 RPS что очень мало.

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

Есть 3 проблемы с которыми я сталкивался на проекте, и хотел бы стабилизировать ситуацию. Чтобы дать еще один шанс запуститься приложению хотя бы без SSR.

  1. Медленные ответы API, бывает что бэк что-то не предусмотрел и на проде запросы стали медленными.

  2. Ошибки JS в режиме SSR, причем в браузере этих ошибок нет. Допустили по неосторожности или другим причинам.

  3. Большая нагрузка при DDOS когда упираемся в оперативку или процессор, надо отключать режим SSR и дать клиенту пустышку чтобы в браузере могло запуститься.

Пообщавшись в девопсами пришли к некоторым правилам которым должно следовать SPA приложение:

  • Отключить SSR при медленном рендере страницы. Делегировать рендер браузеру.

  • Даунгрейд должен быть не во всем СПА, а только там где есть проблема.

  • В случае больших нагрузок и когда рендер всё медленнее и медленнее надо следить за этим, и на время отключить SSR во всём приложении, спустя время в автоматическом режиме включать снова.

  • Отключать SSR принудительно на некоторых страницах где он не нужен, чтобы не грузить сервер.

  • Добавить кеш и storage держать в redis

Написал в общем модуль который всё это делает в автоматическом режиме. Для достижения максимального эффекта надо еще добавить модуль кеширования (например nuxt-ssr-cache).

npm install @drozd/nuxt-performance

Далее идём в nuxt.config.js

module.exports = {
  performance: {
    // логирование времени запросов
    renderRouteTimeCallback: (route, ms) => {
      console.log(`time render route: ${route} ${ms} ms`);
    },
    // отключаем SSR на нужных нам роутах
    isOnlySPA: (route, _context) => {
      return route === '/personal';
    },
    // кол-во допустимых мс для рендера при SSR
    maxRenderTime: 1000,
    // кол-во попыток отрисовать SSR если рендер медленный, 
    // дальше выключаем на указнное время timeDisabledSsrWithRoute
    maxAttemptSsr: 5,
    // RegExp страниц исключения для модуля в целом
    excludeRoutes: /healthcheck/, 
    // на какое время выключаем сср для страницы
    timeDisabledSsrWithRoute: 1000 * 60, 
    // интервал очистки общего счётчика, когда выключили SSR на всём сайте
    clearSlowCounterIntervalTime: 1000 * 60 * 5, 
    // Общее кол-во медленных запросов на сайте, потом отключаем SSR везде 
    maxSlowCount: 50
  }

  // ...
};

После внедрения данного модуля и настройке кеширования всех страниц на 10сек мы получили прирост RPS в ~15раз, с 30 до 500 результат плавающий, зависит от выделенных ресурсов админами :)

Репозиторий https://github.com/gustoase/nuxt-performance

Если у вас есть опыт по оптимизациям, пишите, всем будет полезно)

Комментарии (0)