---
title: "Três Bibliotecas Lua Resty Comumente Usadas no OpenResty - API7.ai"
description: "Vamos aprender as bibliotecas Lua Resty comumente usadas no OpenResty: `lua-resty-ngxvar`, `lua-rapidjson` e `lua-resty-worker-events`."
url: "https://api7.ai/pt/learning-center/openresty/lua-resty-libraries-in-openresty"
---

# Três Bibliotecas Lua Resty Comumente Usadas no OpenResty

API7.ai

January 13, 2023

[OpenResty (NGINX + Lua)](https://api7.ai/learning-center/openresty)

Aprender sobre linguagens de programação e plataformas geralmente é uma questão de entender as bibliotecas padrão e de terceiros, em vez da sintaxe em si. Depois de aprender sua API e técnicas de otimização de desempenho, precisamos aprender o uso de várias bibliotecas `lua-resty` para expandir nossas capacidades do OpenResty para mais cenários.

## Onde encontrar a biblioteca `lua-resty`?

Comparado ao PHP, Python e JavaScript, as bibliotecas padrão e de terceiros do OpenResty ainda são relativamente escassas, e encontrar as bibliotecas `lua-resty` certas não é fácil. No entanto, aqui estão duas fontes recomendadas para ajudá-lo a encontrá-las mais rapidamente.

A primeira recomendação é o repositório [`awesome-resty`](https://github.com/bungle/awesome-resty) mantido por Aapo. Este repositório organiza as bibliotecas relacionadas ao OpenResty por categoria e é abrangente, incluindo módulos C do NGINX, bibliotecas `lua-resty`, frameworks web, bibliotecas de roteamento, templates, frameworks de teste, etc. É sua primeira escolha para recursos do OpenResty.

Se você não encontrar a biblioteca certa no repositório de Aapo, também pode consultar o `luarocks`, `topm` ou GitHub. Pode haver algumas bibliotecas que não foram open-source por muito tempo e não receberam muita atenção.

Nos artigos anteriores, aprendemos sobre várias bibliotecas úteis, como `lua-resty-mlcache`, `lua-resty-traffic`, `lua-resty-shell`, etc. Hoje, no último artigo da seção de otimização de desempenho do OpenResty, conheceremos mais 3 bibliotecas periféricas únicas, todas contribuídas por desenvolvedores da comunidade.

## Melhoria de desempenho do `ngx.var`

Primeiro, vamos ver um módulo C: [`lua-var-nginx-module`](https://github.com/api7/lua-var-nginx-module). Como mencionei anteriormente, `ngx.var` é uma operação relativamente custosa em termos de desempenho. Assim, na prática, precisamos usar `ngx.ctx` como uma camada de cache.

Então, existe alguma maneira de resolver completamente o problema de desempenho do `ngx.var`?

Este módulo C faz algumas experiências nessa área, e os resultados são notáveis, com uma melhoria de desempenho de 5x em relação ao `ngx.var`. Ele usa a abordagem `FFI`, então você precisa compilar o OpenResty com a seguinte opção de compilação primeiro.

```
./configure --prefix=/opt/openresty \
         --add-module=/path/to/lua-var-nginx-module
```

Em seguida, use `luarocks` para instalar a biblioteca lua da seguinte forma:

```
luarocks install lua-resty-ngxvar
```

O método chamado aqui também é muito simples, exigindo apenas uma linha da função `fetch`. Funciona igual ao `ngx.var.remote_addr` original para obter o endereço IP do cliente.

```
content_by_lua_block {
    local var = require("resty.ngxvar")
    ngx.say(var.fetch("remote_addr"))
}
```

Depois de entender essas operações básicas, você pode ficar mais curioso sobre como este módulo alcança uma melhoria significativa de desempenho. Como sempre dizemos, "não há segredos diante do código-fonte". Então, vamos descobrir como buscar a variável `remote_addr`.

```
ngx_int_t
ngx_http_lua_var_ffi_remote_addr(ngx_http_request_t *r, ngx_str_t *remote_addr)
{
    remote_addr->len = r->connection->addr_text.len;
    remote_addr->data = r->connection->addr_text.data;

    return NGX_OK;
}
```

Depois de ler este código, você verá que esta abordagem Lua `FFI` é a mesma que a abordagem do `lua-resty-core`. Tem a vantagem óbvia de usar `FFI` para obter variáveis diretamente, contornando a lógica de busca original do `ngx.var`. Sua desvantagem é óbvia: adicionar funções C e chamadas `FFI` para cada variável que você deseja obter, o que consome tempo e energia.

Alguém pode perguntar: "Por que eu diria que isso consome tempo e energia? O código C acima não parece substancial?" Vamos dar uma olhada na origem dessas linhas de código, que vêm de `src/http/ngx_http_variables.c` no código do NGINX.

```
static ngx_int_t
ngx_http_variable_remote_addr(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{
    v->len = r->connection->addr_text.len;
    v->valid = 1;
    v->no_cacheable = 0;
    v->not_found = 0;
    v->data = r->connection->addr_text.data;

    return NGX_OK;
}
```

Depois de ver o código-fonte, o mistério é revelado! `lua-var-nginx-module` é um portador do código de variáveis do NGINX, com o empacotamento FFI na camada externa, e dessa forma, alcança a otimização de desempenho. Esta é uma boa ideia e uma boa direção para otimização.

Ao aprender uma biblioteca ou uma ferramenta, não devemos parar apenas no nível da operação, mas também perguntar por que fazemos isso e olhar o código-fonte. Claro, também encorajo fortemente você a contribuir com código para suportar mais variáveis do NGINX.

## JSON Schema

Aqui, apresento uma biblioteca `lua-resty`: [`lua-rapidjson`](https://github.com/xpol/lua-rapidjson). É um wrapper em torno do `rapidjson`, a biblioteca JSON open-source da Tencent, conhecida por seu desempenho. Aqui, focamos na diferença entre ela e o `cjson`: suporte a `JSON Schema`.

`JSON Schema` é um padrão comum que nos permite descrever com precisão o formato dos parâmetros em uma interface e como eles devem ser validados. Aqui está um exemplo simples:

```
"stringArray": {
    "type": "array",
    "items": { "type": "string" },
    "minItems": 1,
    "uniqueItems": true
}
```

Este JSON descreve com precisão que o parâmetro `stringArray` é do tipo array de strings e que o array não pode estar vazio, nem os elementos do array podem ser duplicados.

`lua-rapidjson` nos permite usar JSON Schema no OpenResty, o que pode trazer grande conveniência para a validação de interfaces. Por exemplo, para a interface de limite de contagem descrita anteriormente, podemos usar o seguinte schema para descrever:

```
local schema = {
    type = "object",
    properties = {
        count = {type = "integer", minimum = 0},
        time_window = {type = "integer",  minimum = 0},
        key = {type = "string", enum = {"remote_addr", "server_addr"}},
        rejected_code = {type = "integer", minimum = 200, maximum = 600},
    },
    additionalProperties = false,
    required = {"count", "time_window", "key", "rejected_code"},
}
```

Você descobrirá que isso pode levar a dois benefícios muito óbvios:

1. Para o front-end, o front-end pode reutilizar diretamente esta descrição de schema para o desenvolvimento de páginas front-end e validação de parâmetros sem precisar se preocupar com o back-end.
2. Para o back-end, o back-end usa diretamente a função de validação de schema `SchemaValidator` do `lua-rapidjson` para determinar a legitimidade da interface, e não há necessidade de escrever código extra.

## Comunicação entre `Worker`s

Finalmente, gostaria de falar sobre a biblioteca `lua-resty` que permite a comunicação entre workers no OpenResty, onde não há um mecanismo de comunicação direta entre workers, o que causa muitos problemas. Vamos imaginar um cenário:

> Um serviço OpenResty tem 24 processos worker, e quando o administrador atualiza uma configuração do sistema através das APIs REST HTTP, apenas um `Worker` recebe a atualização do administrador e escreve o resultado no banco de dados, atualizando o `shared dict` e o `lru cache` dentro de seu próprio Worker. Então, como os outros 23 workers podem ser notificados para atualizar esta configuração?

Um mecanismo de notificação entre múltiplos `Worker`s é necessário para realizar a tarefa acima. No caso de o OpenResty não suportar isso, temos que salvar o dia com dados `shared dict` entre workers.

[`lua-resty-worker-events`](https://github.com/Kong/lua-resty-worker-events) é uma implementação concreta dessa ideia. Ele mantém um número de versão em um `shared dict`, e quando uma nova mensagem é publicada, ele adiciona um ao número de versão e coloca o conteúdo da mensagem no dicionário com o número de versão como `key`.

```
event_id, err = _dict:incr(KEY_LAST_ID, 1)
success, err = _dict:add(KEY_DATA .. tostring(event_id), json)
```

Além disso, um loop de `polling` com um intervalo padrão de 1 segundo é criado em segundo plano usando `ngx.timer` para verificar constantemente as mudanças no número de versão:

```
local event_id, err = get_event_id()
if event_id == _last_event then
    return "done"
end
```

Dessa forma, assim que uma nova notificação de evento for encontrada para ser processada, o conteúdo da mensagem é recuperado do `shared dict` com base no número de versão:

```
while _last_event < event_id do
    count = count + 1
    _last_event = _last_event + 1
    data, err = _dict:get(KEY_DATA..tostring(_last_event))
end
```

No geral, embora `lua-resty-worker-events` tenha um atraso de um segundo, ele ainda implementa um mecanismo de notificação de eventos entre Workers.

No entanto, em alguns cenários em tempo real, como o envio de mensagens, a falta de comunicação direta entre processos `Worker` do OpenResty pode causar alguns problemas. Não há uma solução melhor para isso, mas se você tiver boas ideias, sinta-se à vontade para discutir no Github. Muitas funcionalidades do OpenResty são impulsionadas pela comunidade para construir um ciclo ecológico virtuoso.

## Resumo

As três bibliotecas que apresentamos hoje são únicas e trazem mais possibilidades para aplicações OpenResty. Finalmente, um tópico interativo: você encontrou alguma biblioteca interessante em torno do OpenResty? Ou o que você descobriu ou se perguntou sobre as bibliotecas mencionadas hoje? Sinta-se à vontade para enviar este artigo para os usuários do OpenResty ao seu redor para trocar e progredir juntos.

Share article link

Share

Related Posts

[![FAQ do OpenResty | Como o OpenResty é usado na prática](https://static.api7.ai/uploads/2023/02/12/jbv9M0zi_Hello%20World%20in%20OpenResty%20%283%29.png)](https://api7.ai/learning-center/openresty/faq-5)

## [FAQ do OpenResty | Como o OpenResty é usado na prática](https://api7.ai/learning-center/openresty/faq-5)

[![Parte 3: Como Construir um API Gateway de Microservices Usando OpenResty](https://static.api7.ai/uploads/2023/02/07/3XJXY9Jy_45.png)](https://api7.ai/learning-center/openresty/how-to-build-a-microservices-api-gateway-part-3)

## [Parte 3: Como Construir um API Gateway de Microservices Usando OpenResty](https://api7.ai/learning-center/openresty/how-to-build-a-microservices-api-gateway-part-3)

Table of Contents

- [Onde encontrar a biblioteca `lua-resty`?](#onde-encontrar-a-biblioteca-lua-resty)
- [Melhoria de desempenho do `ngx.var`](#melhoria-de-desempenho-do-ngxvar)
- [JSON Schema](#json-schema)
- [Comunicação entre `Worker`s](#comunica%C3%A7%C3%A3o-entre-workers)
- [Resumo](#resumo)
