Subprojetos por trás do OpenResty
API7.ai
September 12, 2022
Como extrair código Lua do nginx.conf
e mantê-lo legível e sustentável? A solução é bastante simples. Vamos ver como implementar isso com o OpenResty.
Primeiro, crie um diretório chamado lua
. Em seguida, colocaremos todos os arquivos .lua
nele.
$ mkdir lua
$ cat lua/hello.lua
ngx.say("hello, world")
Segundo, use content_by_lua_block
para substituir content_by_lua_file
no arquivo nginx.conf
.
pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
server {
listen 8080;
location / {
content_by_lua_file lua/hello.lua;
}
}
}
Terceiro, reinicie os serviços do OpenResty, e está feito!
$ sudo kill -HUP `cat logs/nginx.pid`
Usando content_by_lua_file
, podemos atualizar o arquivo Lua diretamente em vez de atualizar o nginx.conf
. Mas surgem algumas questões:
- Usamos um caminho relativo na seção
content_by_lua_file lua/hello.lua
. Como o OpenResty encontra o arquivo Lua real? - Após modificar os códigos Lua, precisamos reiniciar o OpenResty para que funcione. Existe alguma maneira de depurar de forma eficiente?
- Como adicionar o diretório que contém os arquivos Lua ao caminho de busca do OpenResty?
Eu encorajo você a pensar sobre essas questões, que podem ser respondidas na documentação oficial. É por isso que sempre enfatizo a importância da documentação.
Para a primeira questão, se o caminho relativo for fornecido, quando o OpenResty iniciar, ele prefixará o -p PATH
nos parâmetros de linha de comando de inicialização do OpenResty e concatenará o caminho relativo em um caminho absoluto. Dessa forma, o OpenResty pode encontrar o arquivo Lua sem problemas.
O segundo problema é que o código Lua é carregado na primeira solicitação e armazenado em cache por padrão. Portanto, toda vez que você alterar o arquivo fonte Lua, precisará recarregar o OpenResty para que funcione. Você pode evitar o recarregamento desativando o lua_code_cache
no nginx.conf
. No entanto, é essencial observar que esse método só pode ser usado temporariamente para desenvolvimento e depuração. Portanto, se você estiver em produção, deve habilitar o cache. Caso contrário, haverá um impacto significativo no desempenho.
Para a última questão, o OpenResty fornece uma diretiva lua_package_path
para definir o caminho de busca para módulos Lua. Por exemplo, podemos definir lua_package_path
como $prefix/lua/?.lua;;
:
$prefix
é o-p PATH
no parâmetro de inicialização./lua/?.lua
indica todos os arquivos no diretório Lua com o sufixo.lua
.- Os dois pontos e vírgula finais representam o caminho de busca de código embutido.
Estrutura de diretórios após a instalação
Após entender o primeiro programa "hello world", vamos ver como é a estrutura de diretórios do OpenResty após a instalação e quais arquivos estão contidos nela.
Primeiro, passamos a opção -V
para ver onde o OpenResty está. Para o seguinte resultado, omiti muitos parâmetros de compilação de módulos, que adicionaremos mais tarde:
$ openresty -V
nginx version: openresty/1.13.6.2
built by clang 10.0.0 (clang-1000.10.44.4)
built with OpenSSL 1.1.0h 27 Mar 2018
TLS SNI support enabled
configure arguments: --prefix=/usr/local/Cellar/openresty/1.13.6.2/nginx ...
Eu uso o brew para instalar o OpenResty no meu Mac. O caminho é /usr/local/Cellar/openresty/1.13.6.2/nginx
, que pode ser diferente no seu ambiente. Esse caminho contém os diretórios bin
, luajit
, lualib
, nginx
, pod
e outros. É essencial entender o significado dessas pastas para que possamos aprender melhor o OpenResty. Então, vamos dar uma olhada nelas uma por uma.
Primeiro, o importante diretório bin
.
$ ll /usr/local/Cellar/openresty/1.13.6.2/bin
total 320
-r-xr-xr-x 1 ming admin 19K 3 27 12:54 md2pod.pl
-r-xr-xr-x 1 ming admin 15K 3 27 12:54 nginx-xml2pod
lrwxr-xr-x 1 ming admin 19B 3 27 12:54 openresty -> ../nginx/sbin/nginx
-r-xr-xr-x 1 ming admin 62K 3 27 12:54 opm
-r-xr-xr-x 1 ming admin 29K 3 27 12:54 resty
-r-xr-xr-x 1 ming admin 15K 3 27 12:54 restydoc
-r-xr-xr-x 1 ming admin 8.3K 3 27 12:54 restydoc-index
Isso contém tanto a CLI do OpenResty, resty
, que mencionamos na seção anterior, quanto o executável principal, openresty
, que na verdade é um link simbólico para o nginx. Quanto às outras ferramentas no diretório, sem dúvida, como o resty
, são todos scripts Perl.
Entre eles, opm
é uma ferramenta de gerenciamento de pacotes que nos permite gerenciar todos os tipos de pacotes de terceiros, que serão abordados em uma seção posterior; e restydoc
, um velho amigo da primeira seção, é um visualizador de documentação fornecido pelo OpenResty, que nos permite visualizar a documentação do OpenResty e do NGINX.
$ restydoc -s ngx.say
$ restydoc -s proxy_pass
Os dois exemplos acima consultam a API do OpenResty e os comandos do NGINX, respectivamente. restydoc
é uma ferramenta muito útil para engenheiros de servidores focados em desenvolvimento.
Depois de navegar pelo diretório bin
, vamos para o diretório pod
.
Primeiro, vamos enfatizar que pod
aqui não tem nada a ver com o conceito de pod no Kubernetes. Em vez disso, o pod
é uma linguagem de marcação usada no Perl para escrever documentação para módulos Perl. E esse diretório contém a documentação do OpenResty
, NGINX
, lua-resty-*
e LuaJIT
, que estão todos vinculados ao restydoc
mencionado anteriormente.
Em seguida, estão os diretórios familiares NGINX
e luajit
. Esses dois são fáceis de entender. Eles armazenam principalmente os arquivos executáveis e dependências do NGINX e do LuaJIT e são a base do OpenResty. Muitas pessoas dizem que o OpenResty é baseado em Lua, mas isso é impreciso. Como podemos ver acima, o OpenResty é na verdade baseado no LuaJIT.
Na verdade, nos estágios iniciais, o OpenResty vinha com Lua e LuaJIT, e podíamos decidir se usaríamos Lua ou LuaJIT por meio de opções de compilação. No entanto, o Lua está sendo descontinuado, e apenas o LuaJIT de maior desempenho é suportado.
Finalmente, vamos olhar para o diretório lualib
. Ele contém as bibliotecas Lua usadas no OpenResty, principalmente divididas em dois diretórios: ngx
e resty
.
- O diretório
ngx
contém os códigos Lua do projeto oficial lua-resty-core, que é uma reimplementação baseada em FFI da API do OpenResty. Vou explicar em um capítulo específico por que precisamos reimplementá-la. - O diretório
resty
contém códigos Lua de vários projetoslua-resty-*
, que abordaremos a seguir.
Seguindo a convenção deste curso, neste ponto vou fornecer a fonte desses diretórios. Essa também é uma das alegrias dos projetos de código aberto. Se você gosta de investigar a fundo, sempre encontrará coisas mais interessantes.
Aqui está o script de empacotamento do OpenResty para o CentOS, que contém todos os diretórios mencionados acima.
%files
%defattr(-,root,root,-)
/etc/init.d/%{name}
/usr/bin/%{name}
%{orprefix}/bin/openresty
%{orprefix}/site/lualib/
%{orprefix}/luajit/*
%{orprefix}/lualib/*
%{orprefix}/nginx/html/*
%{orprefix}/nginx/logs/
%{orprefix}/nginx/sbin/*
%{orprefix}/nginx/tapset/*
%config(noreplace) %{orprefix}/nginx/conf/*
%{orprefix}/COPYRIGHT
Visão geral do projeto OpenResty
Quando falamos do OpenResty, pensamos no lua-nginx-module
. Sim, esse módulo C do NGINX é de fato o núcleo do OpenResty, mas não é equivalente ao OpenResty. Muitos engenheiros chamam o OpenResty de ngx + lua
, o que também é usado em livros compartilhados e publicados em muitas conferências técnicas. Isso não é rigoroso e não é defendido pela comunidade OpenResty.
Vou falar sobre o porquê e quais outros projetos relacionados, além do lua-nginx-module
, estão no OpenResty.
Abra a página inicial do projeto OpenResty no GitHub, e você verá que o OpenResty contém 68 projetos públicos, que são divididos aproximadamente nas seguintes sete categorias. Vou apresentá-las brevemente para que você possa ter uma impressão inicial e aprendê-las rapidamente.
Módulos C do NGINX
A nomenclatura dos projetos do OpenResty é padronizada, e aqueles chamados *-nginx-module
são os módulos C do NGINX.
Há mais de 20 módulos C no OpenResty, e podemos encontrá-los usando openresty -V
, que usamos no início desta seção.
$ openresty -V
nginx version: openresty/1.13.6.2
built by clang 10.0.0 (clang-1000.10.44.4)
built with OpenSSL 1.1.0h 27 Mar 2018
TLS SNI support enabled
configure arguments: --prefix=/usr/local/Cellar/openresty/1.13.6.2/nginx --with-cc-opt='-O2 -I/usr/local/include -I/usr/local/opt/pcre/include -I/usr/local/opt/openresty-openssl/include' --add-module=../ngx_devel_kit-0.3.0 --add-module=../echo-nginx-module-0.61 --add-module=../xss-nginx-module-0.06 --add-module=../ngx_coolkit-0.2rc3 --add-module=../set-misc-nginx-module-0.32 --add-module=../form-input-nginx-module-0.12 --add-module=../encrypted-session-nginx-module-0.08 --add-module=../srcache-nginx-module-0.31 --add-module=../ngx_lua-0.10.13 --add-module=../ngx_lua_upstream-0.07 --add-module=../headers-more-nginx-module-0.33 --add-module=../array-var-nginx-module-0.05 --add-module=../memc-nginx-module-0.19 --add-module=../redis2-nginx-module-0.15 --add-module=../redis-nginx-module-0.3.7 --add-module=../ngx_stream_lua-0.0.5 --with-ld-opt='-Wl,-rpath,/usr/local/Cellar/openresty/1.13.6.2/luajit/lib -L/usr/local/lib -L/usr/local/opt/pcre/lib -L/usr/local/opt/openresty-openssl/lib' --pid-path=/usr/local/var/run/openresty.pid --lock-path=/usr/local/var/run/openresty.lock --conf-path=/usr/local/etc/openresty/nginx.conf --http-log-path=/usr/local/var/log/nginx/access.log --error-log-path=/usr/local/var/log/nginx/error.log --with-pcre-jit --with-ipv6 --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module --with-http_v2_module --without-mail_pop3_module --without-mail_imap_module --without-mail_smtp_module --with-http_stub_status_module --with-http_realip_module --with-http_addition_module --with-http_auth_request_module --with-http_secure_link_module --with-http_random_index_module --with-http_geoip_module --with-http_gzip_static_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-threads --with-dtrace-probes --with-stream --with-stream_ssl_module --with-http_ssl_module
Aqui, --add-module=
é seguido pelos módulos C do OpenResty. Os principais são lua-nginx-module
e stream-lua-nginx-module
, o primeiro para lidar com tráfego de camada 7 e o segundo para dirigir tráfego de camada 4.
Alguns desses módulos C exigem atenção especial e não são recomendados, embora sejam compilados no OpenResty por padrão. Por exemplo, redis2-nginx-module
, redis-nginx-module
e memc-nginx-module
são usados para interoperar com Redis e Memcached. Essas bibliotecas C foram recomendadas pelo OpenResty nos estágios iniciais, mas foram substituídas por lua-resty-redis
e lua-resty-memcached
após a adição do recurso cosocket
, e são mantidas inativas.
O OpenResty não desenvolverá mais bibliotecas C do NGINX no futuro, mas se concentrará na biblioteca Lua baseada em cosocket
, que é o futuro.
Bibliotecas lua-resty-*
O repositório oficial do OpenResty contém 18 bibliotecas lua-resty-*
, incluindo Redis, MySQL, Memcached, WebSocket, DNS, controle de tráfego, processamento de strings, cache em processo e outras bibliotecas padrão. Além das oficiais que vêm com elas, há mais bibliotecas de terceiros. Elas são essenciais, e dedicaremos mais tempo a essas bibliotecas na próxima seção.
Ramo LuaJIT mantido pelo próprio OpenResty
O OpenResty mantém seu próprio ramo LuaJIT além de seu próprio patch OpenSSL. Em 2015, o autor do LuaJIT, Mike Pall, anunciou sua aposentadoria para encontrar um novo mantenedor do LuaJIT, mas Mike não encontrou um mantenedor adequado. Ele agora está principalmente fazendo manutenção de correções de bugs, e o desenvolvimento de novos recursos foi suspenso, então o OpenResty mantém seu próprio ramo LuaJIT.
Comparado ao Lua, o LuaJIT adiciona muitas funções essenciais e únicas, mas poucos engenheiros as conhecem, então são habilidades semi-ocultas que apresentarei mais tarde.
Framework de Testes
O framework de testes do OpenResty é o test-nginx, também desenvolvido em Perl, e como você pode ver pelo nome, ele é projetado especificamente para testar projetos relacionados ao NGINX. Todos os casos de teste oficiais do OpenResty para módulos C e a biblioteca lua-resty
são conduzidos pelo test-nginx
. Este é um sistema muito mais poderoso e independente, ao contrário dos frameworks comuns baseados em asserções.
Alguns contribuidores do OpenResty ainda não entenderam esse framework de testes e às vezes enviam PRs que contêm códigos C e Lua complexos, mas ainda são frequentemente intimidados pela ideia de escrever casos de teste correspondentes. Então, se você olhou para alguns dos casos de teste no diretório /t
do projeto OpenResty e ainda está confuso, não duvide de si mesmo ainda. A maioria das pessoas é assim.
Além do test-nginx
, o projeto mockeagain simula uma rede lenta, permitindo que os programas leiam e escrevam um byte por vez. Esta é uma ferramenta muito útil para servidores web.
Ferramentas de Depuração
O projeto OpenResty gastou muito esforço em como depurar códigos de forma científica e dinâmica.
Os dois projetos OpenResty, openresty-systemtap-toolkit e stapxx, são baseados no systemtap
, uma ferramenta de depuração e rastreamento dinâmico. A maior vantagem de usar um systemtap
é que ele permite a análise in vivo enquanto é completamente não intrusivo para o aplicativo alvo.
Por exemplo, um systemtap
é como ir ao hospital e fazer uma tomografia computadorizada, indolor e imperceptível. Ainda melhor, o systemtap
pode gerar gráficos de chama visuais para análise de desempenho, que descreverei mais tarde, então aqui está um gráfico de chama para dar uma ideia do que está acontecendo.
Empacotamento
Os scripts de empacotamento do OpenResty em diferentes sistemas operacionais de distribuição (como CentOS, Ubuntu, macOS, etc.) são escritos manualmente para maior controle. Quando introduzimos a estrutura de diretórios após a instalação, já cobrimos esses projetos relacionados ao empacotamento: openresty-packaging e home-brew. Se você estiver interessado nisso, pode aprender por conta própria, e não repetirei aqui.
Ferramentas de Engenharia
Além desses projetos maiores, o OpenResty tem várias ferramentas de engenharia que são principalmente ocultas.
Por exemplo, openresty-devel-utils é o conjunto de ferramentas para desenvolver OpenResty e NGINX. Claro, elas também são desenvolvidas em Perl, e a maioria das ferramentas não está documentada. Mas para desenvolvedores do OpenResty, essas ferramentas são muito úteis. Vou