upstream: Модуль балансировки нагрузки и резервирования соединений для nginx-module-lua
Установка
Если вы еще не настроили подписку на репозиторий RPM, зарегистрируйтесь. После этого вы можете продолжить с следующими шагами.
CentOS/RHEL 7 или Amazon Linux 2
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 lua-resty-upstream
CentOS/RHEL 8+, Fedora Linux, Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install lua5.1-resty-upstream
Чтобы использовать эту библиотеку Lua с NGINX, убедитесь, что nginx-module-lua установлен.
Этот документ описывает lua-resty-upstream v0.10, выпущенный 19 декабря 2019 года.
Модуль балансировки нагрузки и резервирования соединений
Обзор
Создайте lua разделяемый словарь. Определите свои upstream пулы и хосты в init_by_lua, это будет сохранено в разделяемом словаре.
Используйте метод connect, чтобы вернуть подключенный tcp сокет.
В качестве альтернативы передайте модуль resty (например, lua-resty-redis или lua-resty-http), который реализует connect() и set_timeout().
Вызовите process_failed_hosts, чтобы обработать неудачные хосты без блокировки текущего запроса.
Используйте resty.upstream.api, чтобы изменить конфигурацию upstream во время инициализации или выполнения, это рекомендуется!
resty.upstream.http оборачивает lua-resty-http от @pintsized.
Это позволяет выполнять резервирование на основе кодов состояния HTTP, а также статуса соединения сокета.
lua_shared_dict my_upstream_dict 1m;
init_by_lua '
upstream_socket = require("resty.upstream.socket")
upstream_api = require("resty.upstream.api")
upstream, configured = upstream_socket:new("my_upstream_dict")
if not upstream then
error(configured)
end
api = upstream_api:new(upstream)
if not configured then -- Переопределение только при запуске, разделяемая память сохраняется между HUP
api:create_pool({id = "primary", timeout = 100})
api:set_priority("primary", 0)
api:set_method("primary", "round_robin")
api:add_host("primary", { id="a", host = "127.0.0.1", port = "80", weight = 10 })
api:add_host("primary", { id="b", host = "127.0.0.1", port = "81", weight = 10 })
api:create_pool({id = "dr"})
api:set_priority("dr", 10)
api:add_host("dr", { host = "127.0.0.1", port = "82", weight = 5 })
api:add_host("dr", { host = "127.0.0.1", port = "83", weight = 10 })
api:create_pool({id = "test", priority = 5})
api:add_host("primary", { id="c", host = "127.0.0.1", port = "82", weight = 10 })
api:add_host("primary", { id="d", host = "127.0.0.1", port = "83", weight = 10 })
end
';
init_worker_by_lua 'upstream:init_background_thread()';
server {
location / {
content_by_lua '
local sock, err = upstream:connect()
upstream:process_failed_hosts()
';
}
}
upstream.socket
new
syntax: upstream, configured = upstream_socket:new(dictionary, id?)
Возвращает новый объект upstream, используя указанное имя словаря. Когда вызывается в init_by_lua, возвращает дополнительную переменную, если словарь уже содержит конфигурацию. Принимает необязательный параметр id, который должен быть уникальным, если несколько экземпляров upstream.socket используют один и тот же словарь.
init_background_thread
syntax: ok, err = upstream:init_background_thread()
Инициализирует фоновый поток, должен быть вызван в init_worker_by_lua.
connect
syntax: ok, err = upstream:connect(client?, key?)
Пытается подключиться к хосту в определенных пулах в порядке приоритета, используя выбранный метод балансировки нагрузки.
Возвращает подключенный сокет и таблицу, содержащую подключенный host, poolid и pool, или nil и сообщение об ошибке.
При передаче сокета или модуля resty он вернет тот же объект после успешного подключения или nil.
Кроме того, методы хеширования могут принимать необязательный key, чтобы определить, как хешировать соединение для определения хоста. По умолчанию используется ngx.var.remote_addr. Это значение игнорируется, когда метод пула - round robin.
resty_redis = require('resty.redis')
local redis = resty_redis.new()
local key = ngx.req.get_headers()["X-Forwarded-For"]
local redis, err = upstream:connect(redis, key)
if not redis then
ngx.log(ngx.ERR, err)
ngx.status = 500
return ngx.exit(ngx.status)
end
ngx.log(ngx.info, 'Connected to ' .. err.host.host .. ':' .. err.host.port)
local ok, err = redis:get('key')
process_failed_hosts
syntax: ok, err = upstream:process_failed_hosts()
Обрабатывает любые неудачные или восстановленные хосты из текущего запроса. Запускает немедленный обратный вызов через ngx.timer.at, не блокируя текущий запрос.
get_pools
syntax: pools = usptream:get_pools()
Возвращает таблицу, содержащую текущую конфигурацию пула и хостов. например,
{
primary = {
up = true,
method = 'round_robin',
timeout = 100,
priority = 0,
hosts = {
web01 = {
host = "127.0.0.1",
weight = 10,
port = "80",
lastfail = 0,
failcount = 0,
up = true,
healthcheck = true
}
web02 = {
host = "127.0.0.1",
weight = 10,
port = "80",
lastfail = 0,
failcount = 0,
up = true,
healthcheck = { interval = 30, path = '/check' }
}
}
},
secondary = {
up = true,
method = 'round_robin',
timeout = 2000,
priority = 10,
hosts = {
dr01 = {
host = "10.10.10.1",
weight = 10,
port = "80",
lastfail = 0,
failcount = 0,
up = true
}
}
},
}
save_pools
syntax: ok, err = upstream:save_pools(pools)
Сохраняет таблицу пулов в разделяемом словаре, pools должен быть в том же формате, что и возвращаемый из get_pools.
sort_pools
syntax: ok, err = upstream:sort_pools(pools)
Генерирует порядок приоритета в разделяемом словаре на основе предоставленной таблицы пулов.
bind
syntax: ok, err = upstream:bind(event, func)
Привязывает функцию, которая будет вызвана при возникновении событий. func должна ожидать 1 аргумент, содержащий данные события.
Возвращает true при успешной привязке или nil и сообщение об ошибке при неудаче.
local function host_down_handler(event)
ngx.log(ngx.ERR, "Host: ", event.host.host, ":", event.host.port, " in pool '", event.pool.id,'" is down!')
end
local ok, err = upstream:bind('host_down', host_down_handler)
Событие: host_up
Срабатывает, когда хост меняет статус с down на up. Данные события представляют собой таблицу, содержащую затронутый хост и пул.
Событие: host_down
Срабатывает, когда хост меняет статус с up на down. Данные события представляют собой таблицу, содержащую затронутый хост и пул.
upstream.api
Эти функции позволяют вам динамически перенастраивать upstream пулы и хосты.
new
syntax: api, err = upstream_api:new(upstream)
Возвращает новый объект api, используя предоставленный объект upstream.
set_method
syntax: ok, err = api:set_method(poolid, method)
Устанавливает метод балансировки нагрузки для указанного пула. В настоящее время поддерживаются методы случайного round robin и хеширования.
create_pool
syntax: ok, err = api:create_pool(pool)
Создает новый пул из таблицы параметров, pool должен содержать как минимум 1 ключ id, который должен быть уникальным в текущем объекте upstream.
Другие допустимые параметры:
methodМетод балансировкиtimeoutТаймаут соединения в мсpriorityПулы с более высоким приоритетом используются позжеread_timeoutkeepalive_timeoutkeepalive_poolstatus_codesСм. status_codes
Хосты не могут быть определены на этом этапе.
Примечание: Идентификаторы преобразуются в строку этой функцией.
Значения по умолчанию для пула:
{ method = 'round_robin', timeout = 2000, priority = 0 }
set_priority
syntax: ok, err = api:set_priority(poolid, priority)
Приоритет должен быть числом, возвращает nil в случае ошибки.
add_host
syntax: ok, err = api:add_host(poolid, host)
Принимает идентификатор пула и таблицу параметров, host должен содержать как минимум host.
Если идентификатор хоста не указан, он будет числовым индексом на основе количества хостов в пуле.
Примечание: Идентификаторы преобразуются в строку этой функцией.
Значения по умолчанию:
{ host = '', port = 80, weight = 0}
remove_host
syntax: ok, err = api:remove_host(poolid, host)
Принимает идентификатор пула и идентификатор хоста для удаления из пула.
down_host
syntax: ok,err = api:down_host(poolid, host)
Вручную помечает хост как неработающий, этот хост не будет автоматически восстановлен.
up_host
syntax: ok,err = api:up_host(poolid, host)
Вручную восстанавливает неработающий хост в пул.
upstream.http
Функции для выполнения http-запросов к upstream хостам.
new
syntax: httpc, err = upstream_http:new(upstream, ssl_opts?)
Возвращает новый http upstream объект, используя предоставленный объект upstream.
ssl_opts - это необязательная таблица для настройки поддержки SSL.
* ssl установите в true, чтобы включить SSL Handshaking, по умолчанию false
* ssl_verify установите в false, чтобы отключить проверку сертификата SSL, по умолчанию true
* sni_host строка, используемая в качестве имени хоста sni, по умолчанию - заголовок Host запроса
lua
https_upstream = Upstream_HTTP:new(upstream_ssl, {
ssl = true,
ssl_verify = true,
sni_host = "foo.example.com"
})
init_background_thread
syntax: ok, err = upstream_http:init_background_thread()
Инициализирует фоновый поток, должен быть вызван в init_worker_by_lua.
Не вызывайте метод init_background_thread в upstream.socket, если используете фоновый поток upstream.http.
request
syntax: res, err_or_conn_info, status? = upstream_api:request(params)
Принимает те же параметры, что и метод request lua-resty-http.
При успешном запросе возвращает объект lua-resty-http и таблицу, содержащую подключенный хост и пул.
Если запрос не удался, возвращает nil, ошибку и предложенный код состояния http.
local ok, err, status = upstream_http:request({
path = "/helloworld",
headers = {
["Host"] = "example.com",
}
})
if not ok then
ngx.status = status
ngx.say(err)
ngx.exit(status)
else
local host = err.host
local pool = err.pool
end
set_keepalive
syntax: ok, err = upstream_http:set_keepalive()
Передает таймаут keepalive / пул из конфигурации пула в метод lua-resty-http set_keepalive.
get_reused_times
syntax: ok, err = upstream_http:get_reused_times()
Передает в метод lua-resty-http get_reused_times.
close
syntax: ok, err = upstream_http:close()
Передает в метод lua-resty-http close.
HTTP Healthchecks
Активные фоновые проверки состояния могут быть включены, добавив параметр healthcheck к хосту.
Значение true включит проверку по умолчанию, GET запрос для /.
Параметр healthcheck также может быть таблицей параметров, действительных для метода request lua-resty-http.
С несколькими дополнительными параметрами:
intervalдля установки времени между проверками состояния, в секундах. Должен быть >= 10с. По умолчанию 60с.timeoutустанавливает таймаут соединения для проверок состояния. По умолчанию устанавливается на значение пула.read_timeoutустанавливает таймаут чтения для проверок состояния. По умолчанию устанавливается на значение пула.status_codesтаблица недопустимых кодов состояния ответа. По умолчанию устанавливается на значение пула.
Неудача фоновой проверки происходит в соответствии с теми же параметрами, что и для фронтенд-запроса, если не переопределено явно.
-- Параметры пользовательской проверки
api:add_host("primary", {
host = 123.123.123.123,
port = 80,
healthcheck = {
interval = 30, -- проверка каждые 30с
timeout = (5*1000), -- 5с таймаут соединения
read_timeout = (15*1000), -- 15с таймаут чтения
status_codes = {["5xx"] = true, ["403"] = true}, -- 5xx и 403 ответы - это неудача
-- параметры resty-http
path = "/check",
headers = {
["Host"] = "domain.com",
["Accept-Encoding"] = "gzip"
}
}
})
-- Параметры проверки по умолчанию
api:add_host("primary", {host = 123.123.123.123, port = 80, healthcheck = true})
GitHub
Вы можете найти дополнительные советы по конфигурации и документацию для этого модуля в репозитории GitHub для nginx-module-upstream.