E se houver um conflito entre as regras do Lua e a configuração do NGINX?

API7.ai

October 13, 2022

OpenResty (NGINX + Lua)

1. O nome e a linguagem do OpenResty

P: Até agora não entendi a origem do nome OpenResty. Além disso, o OpenResty decola com a linguagem Lua, então por que não com outras linguagens de script? Por exemplo, Shell, etc.

R: O OpenResty começou como um projeto corporativo da Yahoo!, que começou em outubro de 2007. O nome "Open" foi tirado de OpenAPI, e "Resty" foi tirado de rest API. Inicialmente, o OpenResty não foi concebido para ser um servidor web e plataforma de desenvolvimento, mas sim uma aplicação como um site.

Quando o OpenResty foi open-source há mais de uma década, muito poucas linguagens suportavam sincronização não bloqueante. Mesmo agora, não muitas linguagens de back-end podem alcançar esse nível de desempenho com o OpenResty. Atualmente, mais desenvolvedores estão usando o OpenResty em gateways de API e soft WAFs, o que é uma escolha natural para os desenvolvedores.

Quanto à linguagem, o OpenResty não é o único projeto que incorpora outras linguagens de desenvolvimento no NGINX. Por exemplo, o NGINX oficialmente incorpora JS; também há projetos open source que incorporam PHP no NGINX.

Normalmente, a escolha da linguagem a ser aproveitada é baseada em fatores como concorrência, JIT e popularidade da linguagem. Para o OpenResty, em 2007, Lua era de fato a melhor escolha. O OpenResty deu uma volta ao escolher perl em vez de Lua em suas versões mais antigas.

2. A prioridade das regras de configuração

P: Quando as regras Lua no OpenResty entram em conflito com o arquivo de configuração do NGINX, por exemplo, o NGINX configurou regras de rewrite, e ao mesmo tempo referencia rewrite_by_lua_file, qual é a prioridade dessas duas regras?

R: Na verdade, depende de como a regra de rewrite do NGINX é escrita, se é um break ou last, o que é declarado na documentação oficial do OpenResty, com um código de exemplo:

 location /foo {
     rewrite ^ /bar;
     rewrite_by_lua 'ngx.exit(503)';
 }
 location /bar {
     ...
 }

Nesta configuração do código de exemplo, ngx.exit(503) não será executado.

No entanto, se você escrever assim, ngx.exit(503) será executado.

rewrite ^ /bar break.

No entanto, recomendo usar o OpenResty para rewrite em vez da configuração do NGINX. Para evitar essa ambiguidade, muita configuração do NGINX é relativamente obscura e exige que você consulte a documentação para entendê-la repetidamente.

3. Por que meu código dá erro?

P: Na função de tabela da extensão LuaJIT, por que as duas linhas de código a seguir dão erro "moudule not found" quando executadas pelo LuaJIT? Estou usando a versão 2.0.5 do LuaJIT.

local new_tab = require('table.new')
# ou
require('table.clear')

# A execução vai reportar erro
luajit: table_luajit.lua:1: module 'table.new' not found:

R: Essas duas linhas de código exigem a versão 2.1 do LuaJIT para rodar, documentado aqui: https://github.com/LuaJIT/LuaJIT/blob/v2.1/doc/extensions.html#L218, Você pode descobrir sobre isso.

Como mencionamos, você precisa prestar atenção especial ao usar o OpenResty, que requer uma versão específica do LuaJIT para rodar corretamente. O OpenResty é baseado no branch LuaJIT 2.1 e fez muitas de suas extensões para o LuaJIT.

Então, ao rodar o código nesta coluna, lembre-se de usar a instalação oficial do OpenResty. Se você adicionar o lua-nginx-module para compilar em cima do NGINX, você ainda vai cair em muitas armadilhas!

4. Confusão sobre valores nulos

P: Algumas coisas confusas que encontrei são ngx.null, nil, null, e "". Quando pesquisei na web, vi que alguém disse que null é uma definição de ngx.null. Quando o Redis retorna, muitas vezes determina se o resultado retornado é nulo ou não, então com qual valor ele é comparado ao fazer a determinação? Há outras armadilhas sobre o uso desses valores? Não entendo esses valores claramente.

R: Antes de responder sua pergunta, sugiro que você use o seguinte código para encontrar uma chave em lua-resty-redis.

local res, err = red:get("dog")

Isso porque o nil do Lua não pode ser usado como valor da tabela, então o OpenResty introduz ngx.null como o valor nulo na tabela.

Podemos imprimir ngx.null e seu tipo com o seguinte código.

# imprimir ngx.null
$ resty -e 'print(ngx.null)'
null
# Imprimir o tipo
$ resty -e 'print(type(ngx.null))'
userdata

Como você pode ver, ngx.null não é nil, mas é do tipo userdata.

Além disso, há muitos valores nulos no OpenResty, como cjson.null, cdata``:NULL e assim por diante, que discutirei mais tarde.

Os únicos valores falsos no OpenResty são nil e false. Então, quando você escreve código como if not res then, você deve ter cuidado, e é melhor mudar para explícito if res ~= nil and res ~= false then, com algo assim, e com cobertura de caso de teste correspondente.

5. O que exatamente é o gateway de API?

P: O que é o gateway de API que foi mencionado no artigo? E NGINX, Tomcat, Apache e outros servidores web?

R: O gateway de API é um gateway usado para gerenciar serviços de forma unificada. Por exemplo, pagamento, login de usuário, etc., são todos serviços fornecidos na forma de APIs, e todos precisam de um gateway para fazer segurança e autenticação unificadas.

O gateway de API pode substituir o NGINX tradicional, Apache para lidar com tráfego norte-sul, mas também no ambiente de microsserviços para lidar com tráfego leste-oeste, é um middleware mais próximo do negócio, em vez do servidor Web subjacente.

Para mais informações sobre a introdução e implementação do gateway de API, consulte o Apache APISIX; Apache APISIX é baseado na implementação do OpenResty.