Перейти к содержанию

lua-upstream: Lua API для управления upstream в NGINX

Установка

Вы можете установить этот модуль в любой дистрибутив на базе RHEL, включая, но не ограничиваясь:

  • RedHat Enterprise Linux 7, 8, 9 и 10
  • CentOS 7, 8, 9
  • AlmaLinux 8, 9
  • Rocky Linux 8, 9
  • Amazon Linux 2 и 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

Включите модуль, добавив следующее в начало файла /etc/nginx/nginx.conf:

load_module modules/ngx_http_lua_upstream_module.so;

Этот документ описывает nginx-module-lua-upstream v0.7, выпущенный 15 мая 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;

        # пример вывода для следующего интерфейса /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("не удалось получить серверы в 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
            }
        }
    }
}

Функции

get_upstreams

синтаксис: names = upstream.get_upstreams()

Получить список имен для всех именованных групп upstream (т.е. явных блоков upstream {}).

Обратите внимание, что неявные группы upstream, созданные с помощью proxy_pass и т.д., исключены.

get_servers

синтаксис: servers = upstream.get_servers(upstream_name)

Получить конфигурации для всех серверов в указанной группе upstream. Обратите внимание, что один сервер может иметь несколько адресов, если его имя сервера может быть разрешено в несколько адресов.

Возвращаемое значение — это таблица Lua, похожая на массив. Каждая запись таблицы — это таблица Lua, похожая на хэш, которая принимает следующие ключи:

  • addr

    адрес(а) сокета. может быть либо строкой Lua, либо таблицей Lua, похожей на массив строк Lua. * backup * fail_timeout * max_fails * name * weight

get_primary_peers

синтаксис: peers = upstream.get_primary_peers(upstream_name)

Получить конфигурации для всех основных (не резервных) пиров в указанной группе upstream.

Возвращаемое значение — это таблица Lua, похожая на массив для всех основных пиров. Каждая запись таблицы — это (вложенная) таблица Lua, похожая на хэш, которая принимает следующие ключи:

  • current_weight
  • effective_weight
  • fail_timeout
  • fails
  • id

    Идентификатор (ID) для пира. Этот ID можно использовать для ссылки на пир в группе в API модификации пиров. * max_fails * name

    Адрес сокета для текущего пира * weight * accessed

    Временная метка для последнего доступа (в секундах с начала эпохи) * checked

    Временная метка для последней проверки (в секундах с начала эпохи) * down

    Указывает на то, что пир был помечен как "неработающий", в противном случае этот ключ отсутствует * conns

    Количество активных соединений с пиром (это требует NGINX 1.9.0 или выше).

get_backup_peers

синтаксис: peers = upstream.get_backup_peers(upstream_name)

Получить конфигурации для всех резервных пиров в указанной группе upstream.

Возвращаемое значение имеет ту же структуру, что и функция get_primary_peers.

set_peer_down

синтаксис: ok, err = upstream.set_peer_down(upstream_name, is_backup, peer_id, down_value)

Установить атрибут "down" (логический) для указанного пира.

Чтобы уникально указать пир, необходимо указать имя upstream, является ли он резервным пиром, и ID пира (начиная с 0).

Обратите внимание, что этот метод изменяет настройки пира только в текущем процессе рабочего процесса Nginx. Вам нужно самостоятельно синхронизировать изменения между всеми рабочими процессами Nginx, если вы хотите изменить настройки на уровне сервера (например, с помощью ngx_lua's ngx.shared.DICT).

Ниже приведен пример. Предположим, у нас есть блок upstream "bar" в 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;
}

тогда

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

выключит основной пир, соответствующий server 127.0.0.2.

Аналогично,

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

выключит резервный пир, соответствующий server 127.0.0.4 ....

Вы можете снова включить пир, предоставив значение false в качестве 4-го аргумента.

current_upstream_name

синтаксис: name = upstream.current_upstream_name()

Возвращает имя проксируемого upstream для текущего запроса. Если для этого запроса нет upstream (нет вызова proxy_pass), или эта функция вызывается на этапе до этапа контента, то возвращаемое значение будет nil. Если порт явно указан в определении upstream или директиве proxy_pass, он будет включен в возвращаемое значение этой функции.

Пример:

-- 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

Обратите внимание, что неявные upstream, созданные с помощью proxy_pass, включены, в отличие от вывода upstream.get_upstreams().

предполагая, что ваш luajit установлен в /opt/luajit:

export LUAJIT_LIB=/opt/luajit/lib

предполагая, что вы используете LuaJIT v2.1:

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

Здесь мы предполагаем, что вы установите nginx в /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

Начиная с NGINX 1.9.11, вы также можете скомпилировать этот модуль как динамический модуль, используя опцию `--add-dynamic-module=PATH` вместо `--add-module=PATH` в команде `./configure` выше. А затем вы можете явно загрузить модуль в вашем `nginx.conf` через директиву [load_module](http://nginx.org/en/docs/ngx_core_module.html#load_module), например,

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

См. также

GitHub

Вы можете найти дополнительные советы по конфигурации и документацию для этого модуля в репозитории GitHub для nginx-module-lua-upstream.