Seu Primeiro Programa OpenResty: Hello World

API7.ai

September 9, 2022

OpenResty (NGINX + Lua)

Quando começamos a aprender uma nova linguagem de desenvolvimento, os tutoriais fornecem um caso simples de hello world. Então, vamos pular a instalação por enquanto e ver como escrever esse caso no OpenResty:

$ resty -e "ngx.say('hello world')"
hello world

Este deve ser o código mais direto de "hello world" que você já viu, semelhante ao Python:

$ python -c 'print("hello world")'
hello world

Por trás disso, está uma manifestação da filosofia do OpenResty. O código deve ser conciso o suficiente para que você se livre da ideia de "do início à desistência". Este post se concentrará no caso do "hello world".

Como mencionamos no post Qual é a diferença entre OpenResty e NGINX, o OpenResty é baseado no NGINX. Então, você pode estar se perguntando: Por que não vemos o NGINX aqui? Não se preocupe, vamos adicionar uma linha de código para ver o que está rodando por trás do resty:

$ resty -e "ngx.say('hello world'); ngx.sleep(10)" &

Adicionamos o método ngx.sleep para que o programa não saia após imprimir a string hello world. Dessa forma, temos a oportunidade de descobrir:

$ ps -ef | grep nginx
root     15944  6380  0 13:59 pts/6    00:00:00 grep --color=auto nginx

Finalmente, o processo do NGINX aparece! Parece que o comando resty essencialmente inicia um serviço NGINX. Então, o que é o resty?

Você pode não ter o OpenResty instalado na sua máquina, então, a seguir, vamos voltar aos passos de instalação que pulamos no início e instalar o OpenResty antes de continuar.

Instalação

Como outros softwares de código aberto, podemos instalar o OpenResty de várias maneiras, como usar o gerenciador de pacotes do sistema operacional, compilar a partir do código-fonte ou usar uma imagem Docker. No entanto, recomendo que você primeiro use um gerenciador de pacotes como yum, apt-get ou brew para instalar o OpenResty. Neste post, usarei o macOS como exemplo:

$ brew tap openresty/brewbrew install openresty

Usar outros sistemas operacionais é semelhante. Primeiro, adicione o URL do repositório do OpenResty ao gerenciador de pacotes e, em seguida, use o gerenciador de pacotes para instalar o OpenResty. Para etapas mais detalhadas, você pode consultar a documentação oficial.

No entanto, há dois problemas por trás dessa instalação aparentemente simples:

  1. Por que não recomendo usar o código-fonte para instalá-lo?
  2. Por que não pode ser instalado diretamente do repositório oficial do sistema operacional, mas precisa configurar outro repositório primeiro?

Por favor, pense nessas duas perguntas primeiro.

Aqui, gostaria de acrescentar mais uma coisa. Vou colocar muitos "porquês" por trás das aparências neste curso. Espero que você possa pensar enquanto aprende coisas novas. Não importa se o resultado está correto ou não. Infelizmente, o pensamento independente também é escasso no campo técnico. Devido à diferença no campo e na profundidade técnica de cada pessoa, os professores inevitavelmente terão opiniões pessoais e erros de conhecimento em qualquer curso. Podemos gradualmente formar nosso próprio sistema técnico fazendo mais alguns "porquês" no processo de aprendizado e entendendo-o.

Muitos engenheiros gostam de construir a partir do código-fonte, e eu também gostava muitos anos atrás. No entanto, ao usar um projeto de código aberto, sempre espero poder configurar e compilar manualmente a partir do código-fonte e modificar alguns parâmetros de compilação. Sinto que essa é a melhor maneira de se adequar ao ambiente desta máquina e maximizar seu desempenho.

Mas não é assim na realidade. Toda vez que compilo o código-fonte, encontro problemas ambientais estranhos e só consigo instalá-lo após tropeçar. Agora entendo que nosso objetivo original é usar projetos de código aberto para resolver necessidades de negócios. Não devemos perder tempo lutando com o ambiente, sem mencionar que gerenciadores de pacotes e tecnologias de contêineres existem justamente para nos ajudar a resolver esses problemas.

Voltando ao tópico. Usar o código-fonte do OpenResty para instalar não só é complicado, mas você também precisa resolver dependências externas como PCRE, OpenSSL, etc., e ainda aplicar manualmente patches na versão correspondente do OpenSSL. Caso contrário, haverá falta de funcionalidade ao lidar com sessões SSL. Por exemplo, APIs Lua como ngx.sleep que causam yield não podem ser usadas. Se você quiser saber mais sobre essa parte, pode consultar a documentação oficial para obter informações mais detalhadas.

O OpenResty está mantendo esses patches no script de pacote OpenSSL por conta própria. Quando o OpenResty atualiza a versão do OpenSSL, ele deve regenerar o patch correspondente e realizar testes de regressão completos.

Source0: https://www.openssl.org/source/openssl-%{version}.tar.gz

Patch0: https://raw.githubusercontent.com/openresty/openresty/master/patches/openssl-1.1.0d-sess_set_get_cb_yield.patch
Patch1: https://raw.githubusercontent.com/openresty/openresty/master/patches/openssl-1.1.0j-parallel_build_fix.patch

Ao mesmo tempo, podemos dar uma olhada no script de pacote do OpenResty no CentOS para ver se há outros pontos ocultos:

BuildRequires: perl-File-Temp
BuildRequires: gcc, make, perl, systemtap-sdt-devel
BuildRequires: openresty-zlib-devel >= 1.2.11-3
BuildRequires: openresty-openssl-devel >= 1.1.0h-1
BuildRequires: openresty-pcre-devel >= 8.42-1
Requires: openresty-zlib >= 1.2.11-3
Requires: openresty-openssl >= 1.1.0h-1
Requires: openresty-pcre >= 8.42-1

Como você pode ver aqui, o OpenResty mantém sua própria versão do OpenSSL, bem como suas próprias versões do zlib e PCRE. No entanto, os dois últimos ajustaram os parâmetros de compilação e não preservaram seus patches.

Portanto, considerando esses fatores, não recomendo compilar o OpenResty a partir do código-fonte, a menos que você já conheça os detalhes.

Deve estar claro para você por que a instalação a partir do código-fonte não é recomendada. Quando respondemos à primeira pergunta, também respondemos à segunda: por que não podemos instalar diretamente dos repositórios oficiais do sistema operacional, mas precisamos configurar outro repositório primeiro?

Isso ocorre porque os repositórios oficiais não estão dispostos a aceitar pacotes de OpenSSL, PCRE e zlib mantidos por terceiros, para evitar confusão para outros usuários que não sabem qual escolher. Por outro lado, o OpenResty precisa de versões específicas das bibliotecas OpenSSL e PCRE para funcionar corretamente, e as versões padrão do sistema são relativamente antigas.

CLI do OpenResty

Após instalar o OpenResty, o CLI resty já está instalado por padrão. É um script Perl, e, como mencionamos antes, as ferramentas do ecossistema OpenResty são todas escritas em Perl, o que é determinado pela preferência técnica do autor do OpenResty.

$ which resty
/usr/local/bin/resty

$ head -n 1 /usr/local/bin/resty
#!/usr/bin/env perl

O CLI resty é muito poderoso, e podemos usar resty -h ou ler a documentação oficial para obter uma lista completa de funcionalidades. A seguir, apresentarei dois recursos interessantes.

$ resty --shdict='dogs 1m' -e 'local dict = ngx.shared.dogs dict:set("Tom", 56) print(dict:get("Tom"))'

56

O exemplo acima mostra uma configuração do Nginx com código Lua, que realiza a configuração e consulta de um dicionário de memória compartilhada. O dogs 1m é uma configuração do Nginx que declara um espaço de memória compartilhada chamado dogs com um tamanho de 1m. A memória compartilhada é usada como um dicionário no código Lua.

Além disso, os parâmetros --http-include e --main-include são usados para configurar o arquivo de configuração do NGINX, então poderíamos reescrever o exemplo acima como:

$ resty --http-conf 'lua_shared_dict dogs 1m;' -e 'local dict = ngx.shared.dogs dict:set("Tom", 56) print(dict:get("Tom"))'

As ferramentas de depuração padrão no mundo OpenResty, como gdb, valgrind, systemtap e Mozilla rr, também podem ser usadas com o resty para facilitar o desenvolvimento e teste normais. Elas correspondem a diferentes comandos do resty, então a implementação interna é simples, apenas uma camada extra de chamadas de linha de comando. Vamos usar o valgrind como exemplo.

$ resty --valgrind -e "ngx.say('hello world'); "

ERROR: failed to run command "valgrind /usr/local/openresty/nginx/sbin/nginx -p /tmp/resty_rJeOWaYGIY/ -c conf/nginx.conf": No such file or directory

Elas não são apenas aplicáveis ao mundo OpenResty, mas também são ferramentas gerais para o lado do servidor, então vamos aprendê-las passo a passo.

Um "hello world" mais formal

O primeiro programa OpenResty que escrevemos, no início, usou o comando resty sem o processo master e sem escutar em portas específicas. Agora, vamos implementar outro programa hello world.

Precisamos de pelo menos três etapas para completá-lo.

  1. Criar um diretório de trabalho.
  2. Modificar o arquivo de configuração do NGINX para incorporar o código Lua nele.
  3. Iniciar o serviço OpenResty.

Vamos começar criando um diretório de trabalho.

$ mkdir openresty-sample
$ cd openresty-sample
$ mkdir logs/ conf/

A seguir está um nginx.conf minimalista com a diretiva content_by_lua do OpenResty no diretório raiz, que incorpora o método ngx.say.

events {
    worker_connections 1024;
}

http {
    server {
        listen 8080;
        location / {
            content_by_lua '
                ngx.say("hello, world")
            ';
        }
    }
}

Certifique-se de que o OpenResty foi adicionado ao ambiente PATH primeiro; em seguida, inicie o serviço OpenResty:

$ openresty -p `pwd` -c conf/nginx.conf

Se nenhum erro ocorrer, o serviço OpenResty foi iniciado com sucesso. Podemos acessá-lo usando o comando cURL para ver os resultados retornados.

$ curl -i 127.0.0.1:8080

HTTP/1.1 200 OK
Server: openresty/1.13.6.2
Content-Type: text/plain
Transfer-Encoding: chunked
Connection: keep-alive
hello, world

Parabéns! O "Hello World" formal no OpenResty está completo!

Resumo

Vamos revisar o que aprendemos hoje. Primeiro, iniciamos a instalação e o CLI do OpenResty com uma simples linha de código "hello, world" e, finalmente, iniciamos o processo OpenResty e executamos um programa de backend real.

Entre eles, o resty é uma ferramenta de linha de comando que usaremos frequentemente no futuro. Portanto, o código de demonstração no curso é executado com ele, em vez de iniciar o serviço OpenResty em segundo plano.

Mais importante, muitos detalhes culturais e técnicos estão ocultos por trás do OpenResty, e é como um iceberg flutuando no mar. Através deste curso, espero mostrar a você um OpenResty mais completo, não apenas suas APIs expostas.