Pular para conteúdo

lua-upstream: API Lua para controle de upstream do NGINX

Instalação

Você pode instalar este módulo em qualquer distribuição baseada em RHEL, incluindo, mas não se limitando a:

  • RedHat Enterprise Linux 7, 8, 9 e 10
  • CentOS 7, 8, 9
  • AlmaLinux 8, 9
  • Rocky Linux 8, 9
  • Amazon Linux 2 e Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install nginx-module-lua-upstream
yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install nginx-module-lua-upstream

Ative o módulo adicionando o seguinte no topo de /etc/nginx/nginx.conf:

load_module modules/ngx_http_lua_upstream_module.so;

Este documento descreve o nginx-module-lua-upstream v0.7 lançado em 15 de maio de 2017.


http {
    upstream foo.com {
        server 127.0.0.1 fail_timeout=53 weight=4 max_fails=100;
        server agentzh.org:81;
    }

    upstream bar {
        server 127.0.0.2;
    }

    server {
        listen 8080;

        # saída de exemplo para a seguinte interface /upstream:
        # upstream foo.com:
        #     addr = 127.0.0.1:80, weight = 4, fail_timeout = 53, max_fails = 100
        #     addr = 106.184.1.99:81, weight = 1, fail_timeout = 10, max_fails = 1
        # upstream bar:
        #     addr = 127.0.0.2:80, weight = 1, fail_timeout = 10, max_fails = 1

        location = /upstreams {
            default_type text/plain;
            content_by_lua_block {
                local concat = table.concat
                local upstream = require "ngx.upstream"
                local get_servers = upstream.get_servers
                local get_upstreams = upstream.get_upstreams

                local us = get_upstreams()
                for _, u in ipairs(us) do
                    ngx.say("upstream ", u, ":")
                    local srvs, err = get_servers(u)
                    if not srvs then
                        ngx.say("falha ao obter servidores no upstream ", u)
                    else
                        for _, srv in ipairs(srvs) do
                            local first = true
                            for k, v in pairs(srv) do
                                if first then
                                    first = false
                                    ngx.print("    ")
                                else
                                    ngx.print(", ")
                                end
                                if type(v) == "table" then
                                    ngx.print(k, " = {", concat(v, ", "), "}")
                                else
                                    ngx.print(k, " = ", v)
                                end
                            end
                            ngx.print("\n")
                        end
                    end
                end
            }
        }
    }
}

Funções

get_upstreams

syntax: names = upstream.get_upstreams()

Obtém uma lista dos nomes de todos os grupos de upstream nomeados (ou seja, blocos upstream {} explícitos).

Observe que grupos de upstream implícitos criados por proxy_pass etc. são excluídos.

get_servers

syntax: servers = upstream.get_servers(upstream_name)

Obtém configurações para todos os servidores no grupo de upstream especificado. Observe que um servidor pode ter vários endereços quando seu nome de servidor pode ser resolvido para múltiplos endereços.

O valor de retorno é uma tabela Lua semelhante a um array. Cada entrada da tabela é uma tabela Lua semelhante a um hash que aceita as seguintes chaves:

  • addr

    endereço(s) do socket. pode ser uma string Lua ou uma tabela Lua semelhante a um array de strings Lua. * backup * fail_timeout * max_fails * name * weight

get_primary_peers

syntax: peers = upstream.get_primary_peers(upstream_name)

Obtém configurações para todos os peers primários (não-backup) no grupo de upstream especificado.

O valor de retorno é uma tabela Lua semelhante a um array para todos os peers primários. Cada entrada da tabela é uma tabela Lua semelhante a um hash (aninhada) que aceita as seguintes chaves:

  • current_weight
  • effective_weight
  • fail_timeout
  • fails
  • id

    Identificador (ID) para o peer. Este ID pode ser usado para referenciar um peer em um grupo na API de modificação de peers. * max_fails * name

    Endereço do socket para o peer atual * weight * accessed

    Timestamp para o último acesso (em segundos desde a Época) * checked

    Timestamp para a última verificação (em segundos desde a Época) * down

    Mantém verdadeiro se o peer foi marcado como "down", caso contrário, esta chave não está presente * conns

    Número de conexões ativas para o peer (isso requer NGINX 1.9.0 ou superior).

get_backup_peers

syntax: peers = upstream.get_backup_peers(upstream_name)

Obtém configurações para todos os peers de backup no grupo de upstream especificado.

O valor de retorno tem a mesma estrutura que a função get_primary_peers.

set_peer_down

syntax: ok, err = upstream.set_peer_down(upstream_name, is_backup, peer_id, down_value)

Define o atributo "down" (booleano) do peer especificado.

Para especificar um peer de forma única, você precisa especificar o nome do upstream, se é ou não um peer de backup, e o ID do peer (começando de 0).

Observe que este método apenas altera as configurações do peer no processo de trabalho atual do NGINX. Você precisa sincronizar as mudanças entre todos os trabalhadores do NGINX se quiser uma alteração em todo o servidor (por exemplo, por meio do ngx_lua's ngx.shared.DICT).

Abaixo está um exemplo. Considere que temos um bloco de upstream "bar" em nginx.conf:

upstream bar {
    server 127.0.0.2;
    server 127.0.0.3 backup;
    server 127.0.0.4 fail_timeout=23 weight=7 max_fails=200 backup;
}

então

upstream.set_peer_down("bar", false, 0, true)

desligará o peer primário correspondente a server 127.0.0.2.

Da mesma forma,

upstream.set_peer_down("bar", true, 1, true)

desligará o peer de backup correspondente a server 127.0.0.4 ....

Você pode ligar um peer novamente fornecendo um valor false como o 4º argumento.

current_upstream_name

syntax: name = upstream.current_upstream_name()

Retorna o nome do upstream proxied para a solicitação atual. Se não houver upstream para esta solicitação (sem chamada proxy_pass), ou se esta função for chamada em uma fase anterior à fase de conteúdo, então o valor de retorno será nil. Se uma porta for explicitamente incluída na definição do upstream ou na diretiva proxy_pass, ela será incluída no valor de retorno desta função.

Exemplo:

-- upstream my_upstream { ... }
-- proxy_pass http://my_upstream;
upstream.current_upstream_name() --> my_upstream

-- proxy_pass http://example.com:1234;
upstream.current_upstream_name() --> example.com:1234

Observe que upstreams implícitos criados por proxy_pass estão incluídos, ao contrário da saída de upstream.get_upstreams().

assumindo que seu luajit está instalado em /opt/luajit:

export LUAJIT_LIB=/opt/luajit/lib

assumindo que você está usando LuaJIT v2.1:

export LUAJIT_INC=/opt/luajit/include/luajit-2.1

Aqui assumimos que você instalaria seu nginx em /opt/nginx/.

./configure --prefix=/opt/nginx \ --with-ld-opt="-Wl,-rpath,$LUAJIT_LIB" \ --add-module=/path/to/lua-nginx-module \ --add-module=/path/to/lua-upstream-nginx-module

make -j2 make install

A partir do NGINX 1.9.11, você também pode compilar este módulo como um módulo dinâmico, usando a opção `--add-dynamic-module=PATH` em vez de `--add-module=PATH` na linha de comando `./configure` acima. E então você pode carregar explicitamente o módulo em seu `nginx.conf` via a diretiva [load_module](http://nginx.org/en/docs/ngx_core_module.html#load_module), por exemplo,

```nginx
load_module /path/to/modules/ngx_http_lua_upstream_module.so;

Veja Também

GitHub

Você pode encontrar dicas adicionais de configuração e documentação para este módulo no repositório GitHub do nginx-module-lua-upstream.