What Is the Difference Between OpenResty and NGINX?
API7.ai
September 9, 2022
Преимущества OpenResty очевидны, но прежде чем углубляться в детали, давайте кратко рассмотрим процесс разработки OpenResty, что поможет вам лучше понять последующий материал.
Процесс разработки OpenResty
OpenResty не создавался с нуля, как другие языки разработки, а основан на зрелых открытых компонентах — NGINX и LuaJIT. OpenResty появился в 2007 году, но его первая версия не использовала Lua, а Perl, что во многом связано с техническими предпочтениями автора.
Однако производительность Perl далека от требований, поэтому во второй версии Perl был заменён на Lua. Тем не менее, в официальном проекте OpenResty Perl всё ещё играет важную роль. Проекты экосистемы OpenResty создаются с использованием Perl, такие как тестовый фреймворк, Linter, CLI и другие. Мы будем постепенно знакомиться с ними позже.
Благодаря высокой производительности и динамическим преимуществам OpenResty, он идеально подходит для нужд CDN-бизнеса, и вскоре стал техническим стандартом для CDN. Более того, благодаря богатым библиотекам lua-resty-*, OpenResty начал постепенно выходить из тени NGINX и формировать свою экосистему, которая широко используется в API-шлюзах, программных WAF и других областях.
Я часто говорю, что OpenResty — это широко используемая технология, но не популярная, что звучит противоречиво. Что это значит?
Он широко используется, потому что OpenResty сейчас является пятым по популярности веб-сервером в мире.
Он не популярен, потому что доля использования OpenResty для построения бизнес-систем невелика. Большинство пользователей используют OpenResty для обработки входящего трафика, не углубляясь в бизнес-логику. Поэтому, естественно, использование OpenResty остаётся поверхностным и достаточным для текущих нужд. Это, конечно, также связано с отсутствием у OpenResty зрелых веб-фреймворков и экосистем, как у Java и Python.
Сказав так много, далее я сосредоточусь на нескольких аспектах, которые делают OpenResty достойным похвалы и изучения.
Основные моменты OpenResty
Подробная документация и тестовые примеры
Да, документация и тестирование — это ключевые показатели надёжности открытого проекта, даже важнее качества кода и производительности.
Документация OpenResty очень подробна, и автор описал каждый момент, на который стоит обратить внимание. В большинстве случаев нам достаточно внимательно изучить документацию, чтобы решить проблему, не прибегая к поиску в Google или анализу исходного кода. Для удобства OpenResty также поставляется с инструментом командной строки restydoc, который помогает просматривать документацию через оболочку, не прерывая процесс кодирования.
Однако в документации доступно лишь несколько фрагментов кода, и нет полных и сложных примеров. Где же найти такие примеры?
Для OpenResty это, естественно, каталог /t, который содержит все тестовые примеры. Каждый тестовый пример включает полную конфигурацию NGINX и код на Lua, а также тестовые входные данные и ожидаемые результаты. Однако тестовый фреймворк OpenResty полностью отличается от других фреймворков с утверждениями, о чём я расскажу позже в отдельной главе.
Синхронное неблокирующее выполнение
Корутины — это новая функция, которую многие скриптовые языки добавили в последние годы для повышения производительности. Но они не идеально реализованы: некоторые являются синтаксическим сахаром, а другие требуют явного объявления ключевых слов.
OpenResty поддерживает корутины с самого начала и реализует синхронную неблокирующую модель программирования. Это важно, потому что программисты — тоже люди, и код должен быть более близок к человеческому мышлению. Явные обратные вызовы и ключевые слова async прерывают мышление и затрудняют отладку.
Так что же такое синхронное неблокирующее выполнение? Давайте сначала поговорим о синхронности. Это очень просто: выполнение происходит последовательно в соответствии с кодом. Например, следующий псевдокод:
local res, err = query-mysql(sql) local value, err = query-redis(key)
В одном запросе, если нам нужно дождаться возврата результата запроса MySQL, прежде чем продолжить запрос к Redis, это синхронное выполнение; если нам не нужно ждать возврата MySQL и мы можем продолжить запрос к Redis, то это асинхронное выполнение. Для OpenResty большинство операций являются синхронными. Только API, связанные с фоновыми таймерами, такие как ngx.timer, являются асинхронными операциями.
Что касается неблокирующего выполнения, это концепция, которую легко спутать с асинхронностью. Когда мы говорим о блокировке здесь, мы имеем в виду блокировку потока операционной системы. Продолжим рассматривать приведённый выше пример, предположим, что запрос к MySQL занимает 1s. Если в течение этих 1s ресурсы операционной системы (CPU) простаивают и просто ждут возврата, это блокирующее выполнение; если CPU использует это время для обработки других запросов, это неблокирующее выполнение. Неблокирующее выполнение также является ключом к реализации высокой конкуренции, такой как C10K и C100K.
Концепция синхронного неблокирующего выполнения важна. Однако, на мой взгляд, эту концепцию не следует понимать по аналогии, потому что неудачная аналогия может ещё больше запутать.
В OpenResty приведённый выше псевдокод может напрямую достичь синхронного неблокирующего выполнения без явных ключевых слов. Это ещё раз подчёркивает, что упрощение использования для разработчиков — одна из концепций OpenResty.
Динамичность
Огромное преимущество OpenResty, которое ещё не полностью раскрыто, — это его динамичность.
Традиционные веб-серверы, такие как NGINX, требуют от нас изменения конфигурационного файла на диске и его перезагрузки для вступления изменений в силу, поскольку они не предоставляют API для управления поведением во время выполнения. Поэтому в микросервисах, требующих частых изменений, NGINX пробовал много раз, но ничего не улучшилось. И внезапное появление Envoy с динамическим API управления xDS представляет серьёзную угрозу для NGINX.
В отличие от NGINX и Envoy, OpenResty управляется скриптовым языком Lua, и динамичность — это естественное преимущество Lua. Например, через API Lua, предоставляемый в модуле lua-nginx-module в OpenResty, мы можем динамически управлять маршрутами, апстримами, SSL-сертификатами, запросами, ответами и т.д. Более того, мы можем изменять логику обработки бизнеса без перезапуска OpenResty, не ограничиваясь API Lua, предоставляемым OpenResty.
Вот отличная аналогия, которая поможет вам понять сказанное о динамичности выше. Просто представьте веб-сервер как автомобиль, который мчится по шоссе: NGINX нужно остановиться, чтобы поменять шины и цвет краски; Envoy может менять шины и цвет во время движения; а OpenResty, помимо этих возможностей, может превратиться в внедорожник, не останавливаясь.
Овладев этой магической способностью, OpenResty расширил свою область компетенции и воображения на другие области, такие как Serverless и Edge computing.
Что следует изучать?
После стольких ключевых особенностей OpenResty, что же нам следует изучать? Я предпочитаю сосредоточиться на основной линии, а не хвататься за всё подряд, чтобы построить систему знаний с чёткой структурой.
Вы должны понимать, что какой бы полной ни была программа курса, она не может охватить все проблемы и не может напрямую помочь вам решить каждый баг и исключение в реальном времени.
Возвращаясь к изучению OpenResty, на мой взгляд, если вы хотите хорошо изучить OpenResty, вам следует понять следующие восемь ключевых моментов:
- Синхронная неблокирующая модель программирования
- Роль различных фаз Request/Response
- Различия между LuaJIT и Lua
- API OpenResty и окружающие библиотеки
- Корутины и cosocket
- Фреймворк для модульного тестирования и инструменты для тестирования производительности
- Флеймграфы и связанные инструменты
- Оптимизация производительности
Эти моменты важны в нашем изучении, и я буду обсуждать их отдельно в каждой главе. Однако в процессе обучения я надеюсь, что вы сможете делать выводы по аналогии и углубляться в некоторые главы в соответствии с вашими интересами и опытом.
Если вы новичок в OpenResty, вы можете следовать прогрессу курса, установить OpenResty в своей среде и запускать и изменять примеры кода. Помните, ваша цель — построить общую картину OpenResty, а не зацикливаться на отдельных моментах. Конечно, если у вас есть вопросы, не стесняйтесь обращаться к нам в чате.
Если вы используете OpenResty в своём проекте, это замечательно! Однако я уверен, что когда вы прочитаете главы о LuaJIT и оптимизации производительности, у вас будет больше резонанса и практических применений, и вы увидите улучшение производительности до и после оптимизации в вашем проекте.
Кроме того, если вы хотите внести вклад в код OpenResty и окружающие библиотеки, самым большим барьером будет не понимание принципов OpenResty или написание модулей NGINX на C, а тестовые примеры и стандарты кода. Я видел слишком много контрибьюторов OpenResty (включая себя), которые многократно изменяли тестовые примеры и стили кода в PR, и существует слишком много негласных правил. Поэтому разделы курса о стандартах кода и модульном тестировании предназначены для вас.
И если вы инженер по качеству, даже если вы не используете OpenResty, тестовый фреймворк и набор инструментов для анализа производительности OpenResty дадут вам много вдохновения. В конце концов, вложения и накопления OpenResty в тестировании довольно глубоки.