Что делать, если возникает конфликт между правилами Lua и конфигурацией NGINX?
API7.ai
October 13, 2022
1. Название и язык OpenResty
Вопрос: Я до сих пор не понял происхождение названия OpenResty. Кроме того, OpenResty использует язык Lua, так почему не другие скриптовые языки? Например, Shell и т.д.
Ответ: OpenResty начался как корпоративный проект Yahoo!, который стартовал в октябре 2007 года. Название "Open" было взято из OpenAPI, а "Resty" — из rest API. Изначально OpenResty не планировался как веб-сервер и платформа для разработки, а скорее как приложение, подобное веб-сайту.
Когда OpenResty был открыт для сообщества более десяти лет назад, очень немногие языки поддерживали синхронное неблокирующее выполнение. Даже сейчас не многие серверные языки могут достичь такого уровня производительности, как OpenResty. В настоящее время больше разработчиков используют OpenResty в API-шлюзах и программных WAF, что является естественным выбором для разработчиков.
Что касается языка, OpenResty — не единственный проект, который встраивает другие языки разработки в NGINX. Например, NGINX официально встраивает JS; также есть открытые проекты, которые встраивают PHP в NGINX.
Обычно выбор языка основывается на таких факторах, как параллелизм, JIT и популярность языка. Для OpenResty в 2007 году Lua действительно был лучшим выбором. OpenResty сделал небольшой крюк, выбрав perl вместо Lua в самых ранних версиях.
2. Приоритет правил конфигурации
Вопрос: Когда правила Lua в OpenResty конфликтуют с конфигурацией NGINX, например, если в NGINX настроены правила rewrite, и одновременно используется rewrite_by_lua_file, то какой приоритет у этих двух правил?
Ответ: На самом деле это зависит от того, как написано правило rewrite в конфигурации NGINX, используется ли break или last, что указано в официальной документации OpenResty, с примером кода:
location /foo { rewrite ^ /bar; rewrite_by_lua 'ngx.exit(503)'; } location /bar { ... }
В этой конфигурации примера ngx.exit(503) не будет выполнен.
Однако, если написать следующим образом, ngx.exit(503) будет выполнен.
rewrite ^ /bar break.
Тем не менее, я рекомендую использовать OpenResty для rewrite вместо конфигурации NGINX. Чтобы избежать этой неоднозначности, большая часть конфигурации NGINX относительно сложна и требует многократного обращения к документации для понимания.
3. Почему мой код выдает ошибку?
Вопрос: В функции таблицы расширения LuaJIT, почему следующие две строки кода выдают ошибку "module not found" при выполнении в LuaJIT? Я использую LuaJIT версии 2.0.5.
local new_tab = require('table.new') # или require('table.clear') # При выполнении выдается ошибка luajit: table_luajit.lua:1: module 'table.new' not found:
Ответ: Эти строки кода требуют LuaJIT версии 2.1 для выполнения, что задокументировано здесь: https://github.com/LuaJIT/LuaJIT/blob/v2.1/doc/extensions.html#L218, вы можете узнать об этом.
Как мы упоминали, при использовании OpenResty нужно быть особенно внимательным, так как он требует определенной версии LuaJIT для корректной работы. OpenResty основан на ветке LuaJIT 2.1 и имеет множество собственных расширений для LuaJIT.
Поэтому, при выполнении кода в этой колонке, пожалуйста, используйте официальную установку OpenResty. Если вы добавите lua-nginx-module для компиляции поверх NGINX, вы все равно столкнетесь с множеством проблем!
4. Путаница с нулевыми значениями
Вопрос: Некоторые вещи, которые меня смущают, это ngx.null, nil, null и "". Когда я искал в интернете, я увидел, что кто-то сказал, что null — это определение ngx.null. Когда Redis возвращает результат, часто проверяется, является ли возвращенный результат null или нет, так с каким значением он сравнивается при проверке? Есть ли другие подводные камни в использовании этих значений? Я не понимаю эти значения четко.
Ответ: Прежде чем я отвечу на ваш вопрос, я предлагаю вам использовать следующий код для поиска ключа в lua-resty-redis.
local res, err = red:get("dog")
Это связано с тем, что nil в Lua не может использоваться как значение таблицы, поэтому OpenResty вводит ngx.null как нулевое значение в таблице.
Мы можем вывести ngx.null и его тип с помощью следующего кода.
# вывод ngx.null $ resty -e 'print(ngx.null)' null # Вывод типа $ resty -e 'print(type(ngx.null))' userdata
Как видите, ngx.null — это не nil, а тип userdata.
Кроме того, в OpenResty есть множество нулевых значений, таких как cjson.null, cdata:NULL и так далее, о которых я расскажу позже.
Единственные ложные значения в OpenResty — это nil и false. Поэтому, когда вы пишете код типа if not res then, нужно быть осторожным, и лучше изменить его на явное if res ~= nil and res ~= false then, с чем-то подобным, и с соответствующим покрытием тестовыми случаями.
5. Что такое API-шлюз?
Вопрос: Что такое API-шлюз, который упоминался в статье? И NGINX, Tomcat, Apache и другие веб-серверы?
Ответ: API-шлюз — это шлюз, используемый для унифицированного управления сервисами. Например, платежи, вход пользователя и т.д., все это сервисы, предоставляемые в виде API, и все они нуждаются в шлюзе для унифицированной безопасности и аутентификации.
API-шлюз может заменить традиционные NGINX, Apache для обработки север-южного трафика, а также в микросервисной среде для обработки восточно-западного трафика, это более близкий к бизнесу middleware, а не базовый веб-сервер.
Для получения дополнительной информации о введении и реализации API-шлюза, пожалуйста, обратитесь к Apache APISIX; Apache APISIX основан на реализации OpenResty.