Главная » Хабрахабр » Nginx-переменные с njs: просто, безболезненно и через JavaScript

Nginx-переменные с njs: просто, безболезненно и через JavaScript

njs — это JavaScript-интерпретатор в легковесном веб-сервере, с помощью которого можно создавать новые nginx-переменные и обработчики стадий запроса. Чем njs хорош? Чего не умеет? И зачем вообще его сделали? На эти и другие вопросы ответит Дмитрий Волынцев (xeioex), разработчик nginx и основной разработчик интерпретатора njs.

— Дмитрий, зачем понадобился скриптинг в конфигах nginx?

— Первая причина — директива if. Люди, которые первый раз ее увидели, думают, что можно использовать ее императивно. На самом деле это не так — конфигурация nginx является декларативной. В примере ниже можно подумать, что в ответе будут два header: X-First и X-Second. Но в ответ попадет только второй header, потому что так устроен nginx: если мы напишем две if-директивы, то выберется самая последняя.

location /only-one-if if ($true) { add_header X-Second 2; }

Вторая причина — то, к чему nginx пришел сейчас. Раньше он использовался для кэширования статики и запросов, а также балансировки нагрузки — классический набор прокси. Распространение микросервисов размыло сферу применения nginx. Если раньше настройка конфигураций заканчивалась на паре location на нескольких бэкендах на каких-то языках, то с микросервисной архитектурой у нас появляется больше движущихся частей. Бэкенд превратился в кучу маленьких компонентов. Логику авторизации, например, необходимо дублировать на каждом микросервисе или выносить ее, скажем, на фронтенд. Чтобы реализовать продвинутую авторизацию, встроенных механизмов решения в nginx хватает не всегда.

В-третьих, в nginx многие директивы принимают динамически вычисляемые выражения, например:

proxy cache bypass $cookie_nocache $arg_nocache;

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

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

— А почему именно JavaScript?

— Мы выбрали JavaScript по нескольким причинам:

  • Современный диалект, что хорошо для разработчиков, переходящих с других языков.
  • С-подобный стиль. Это важно, потому что в конфиге nginx используются фигурные скобки, и в будущем мы хотим добавить возможность написания кода на JS прямо внутри конфига. Фигурные скобки нам в этом помогут. В Lua, например, роль фигурных скобок выполняют begin и end — это неудобно.
  • Модель JavaScript хорошо ложится на архитектуру nginx.

— Значит, Lua тоже рассматривали? Неужели из-за begin и end?

— Уже существует готовый сторонний проект OpenResty. Если не вдаваться в подробности, то это, по сути, nginx + Lua, но он имеет архитектуру, которая идет вразрез с nginx. Мы хотели избежать пересечений с этой экосистемой. Кроме того, есть еще несколько причин:

  • Lua имеет pascal-подобный синтаксис.
  • Массивы индексируются с 1.
  • Lua — этой все-таки нишевый язык программирования.

— Как njs работает в сравнении с конкурентами?

— Мы оценили njs в сравнении с известными движками — V8 и SpiderMonkey. Они неэффективны для задач внутри nginx, потому что заточены под браузеры и очень тяжеловесны, а nginx необходима высокая скорость работы. Кроме того, оба этих движка быстро эволюционируют, их API нестабилен. Наконец, njs может более эффективно встраиваться в nginx:


Количество контекстов, создаваемых в секунду

— Какие стандарты поддерживает njs?

— На данный момент реализованы практически все основные элементы спецификации ECMAScript 5.1 с некоторым вкраплением элементов спецификаций 6 и 7. То есть стандартные объекты типа Object, Array, String, Number, Date, RegExp, JSON. Полноценно поддерживаются замыкания, анонимные функции, работа с исключениями.

Так что на данный момент отсутствует поддержка eval(), и пока что добавлять ее мы не планируем. Мы не ставим своей первоочередной целью полное соответствие спецификации языка. Зато планируем добавить поддержку ключевых слов const и let, а также стрелочных функций.


Что умеет и чего не умеет njs на данный момент

Большинство современных языков самостоятельно следят за временем жизни объектов. Важно упомянуть еще кое-что: отсутствие сборки мусора. Без этого механизма нельзя обойтись, но обычно для него приходится чем-то жертвовать — работа программы замедляется или вообще приостанавливается. Если объект больше не используется, то он автоматически удаляется. В njs память не освобождается до тех пор, пока объект запроса не будет освобожден.

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

— Чем njs не является?

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

Что стоит заранее учитывать?
Теперь непосредственно сам вопрос.

  • njs — это не замена Node.js.
  • Связка nginx + njs — это не application server.
  • njs не реализует полноценно стандарты ECMAScript, поскольку здесь нет поддержки eval().

Если для вас эта тема крайне актуальна и вы жаждите больше деталей, рекомендуем посмотреть видеозаписью доклада Дмитрия Волынцева на HighLoad++ Siberia 2018, где он раскрыл ее со всех сторон.

Также мы приглашаем всех профи к подаче своих докладов на ноябрьскую конференцию HighLoad++ 2018, которая пройдет в Сколково 8 и 9 ноября. Если у вас есть уникальный и интересный опыт и вы готовы им поделиться — до 1 сентября регистрируйтесь и заполняйте форму.

Если боитесь выступать публично — у нас есть так называемая школа докладчиков, где мы бесплатно помогаем прокачивать эти скилы.


Оставить комментарий

Ваш email нигде не будет показан
Обязательные для заполнения поля помечены *

*

x

Ещё Hi-Tech Интересное!

[Перевод] Китайская панель биомаркеров старения

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

Как работает stack trace на ARM

Добрый день! Несколько дней назад столкнулся с небольшой проблемой в нашем проекте — в обработчике прерывания gdb неправильно выводил stack trace для Cortex-M. Поэтому в очередной раз полез выяснять, а какими способами можно получать stack trace для ARM? Какие флаги ...