upstream: Upstream-Verbindungslastenausgleich und Failover-Modul für nginx-module-lua
Installation
Wenn Sie das RPM-Repository-Abonnement noch nicht eingerichtet haben, melden Sie sich an. Danach können Sie mit den folgenden Schritten fortfahren.
CentOS/RHEL 7 oder 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
Um diese Lua-Bibliothek mit NGINX zu verwenden, stellen Sie sicher, dass nginx-module-lua installiert ist.
Dieses Dokument beschreibt lua-resty-upstream v0.10, das am 19. Dezember 2019 veröffentlicht wurde.
Upstream-Verbindungslastenausgleich und Failover-Modul
Übersicht
Erstellen Sie ein lua shared dictionary. Definieren Sie Ihre Upstream-Pools und Hosts in init_by_lua, dies wird im Shared Dictionary gespeichert.
Verwenden Sie die connect-Methode, um einen verbundenen tcp socket zurückzugeben.
Alternativ können Sie ein Resty-Modul (z. B. lua-resty-redis oder lua-resty-http) übergeben, das connect() und set_timeout() implementiert.
Rufen Sie process_failed_hosts auf, um fehlgeschlagene Hosts zu behandeln, ohne die aktuelle Anfrage zu blockieren.
Verwenden Sie resty.upstream.api, um die Upstream-Konfiguration während der Initialisierung oder zur Laufzeit zu ändern, dies wird empfohlen!
resty.upstream.http umschließt die lua-resty-http von @pintsized.
Es ermöglicht Failover basierend auf HTTP-Statuscodes sowie dem Status der Socket-Verbindung.
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 -- Nur bei Start neu konfigurieren, der Shared Memory bleibt bei einem HUP bestehen
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?)
Gibt ein neues Upstream-Objekt unter Verwendung des angegebenen Dictionary-Namens zurück. Wenn es in init_by_lua aufgerufen wird, gibt es eine zusätzliche Variable zurück, wenn das Dictionary bereits eine Konfiguration enthält. Nimmt einen optionalen id-Parameter, dieser muss eindeutig sein, wenn mehrere Instanzen von upstream.socket dasselbe Dictionary verwenden.
init_background_thread
syntax: ok, err = upstream:init_background_thread()
Initialisiert den Hintergrund-Thread, sollte in init_worker_by_lua aufgerufen werden.
connect
syntax: ok, err = upstream:connect(client?, key?)
Versucht, sich mit einem Host in den definierten Pools in Prioritätsreihenfolge unter Verwendung der ausgewählten Lastenausgleichsmethode zu verbinden.
Gibt einen verbundenen Socket und eine Tabelle mit dem verbundenen host, poolid und pool oder nil und eine Fehlermeldung zurück.
Wenn ein socket oder Resty-Modul übergeben wird, wird dasselbe Objekt nach erfolgreicher Verbindung oder nil zurückgegeben.
Zusätzlich können Hash-Methoden einen optionalen key annehmen, um zu definieren, wie die Verbindung gehasht wird, um den Host zu bestimmen. Standardmäßig wird ngx.var.remote_addr verwendet. Dieser Wert wird ignoriert, wenn die Methode des Pools Round Robin ist.
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()
Verarbeitet alle fehlgeschlagenen oder wiederhergestellten Hosts aus der aktuellen Anfrage. Erzeugt einen sofortigen Callback über ngx.timer.at, blockiert jedoch nicht die aktuelle Anfrage.
get_pools
syntax: pools = usptream:get_pools()
Gibt eine Tabelle mit der aktuellen Pool- und Hostkonfiguration zurück. z.B.
{
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)
Speichert eine Tabelle von Pools im Shared Dictionary, pools muss im selben Format wie von get_pools zurückgegeben sein.
sort_pools
syntax: ok, err = upstream:sort_pools(pools)
Erzeugt eine Prioritätsreihenfolge im Shared Dictionary basierend auf der bereitgestellten Tabelle von Pools.
bind
syntax: ok, err = upstream:bind(event, func)
Bindet eine Funktion, die aufgerufen wird, wenn Ereignisse auftreten. func sollte 1 Argument erwarten, das die Ereignisdaten enthält.
Gibt true bei erfolgreicher Bindung oder nil und eine Fehlermeldung bei Fehler zurück.
local function host_down_handler(event)
ngx.log(ngx.ERR, "Host: ", event.host.host, ":", event.host.port, " im Pool '", event.pool.id,'" ist ausgefallen!')
end
local ok, err = upstream:bind('host_down', host_down_handler)
Ereignis: host_up
Ausgelöst, wenn ein Host seinen Status von down auf up ändert. Ereignisdaten sind eine Tabelle, die den betroffenen Host und Pool enthält.
Ereignis: host_down
Ausgelöst, wenn ein Host seinen Status von up auf down ändert. Ereignisdaten sind eine Tabelle, die den betroffenen Host und Pool enthält.
upstream.api
Diese Funktionen ermöglichen es Ihnen, Upstream-Pools und Hosts dynamisch neu zu konfigurieren.
new
syntax: api, err = upstream_api:new(upstream)
Gibt ein neues API-Objekt unter Verwendung des bereitgestellten Upstream-Objekts zurück.
set_method
syntax: ok, err = api:set_method(poolid, method)
Setzt die Lastenausgleichsmethode für den angegebenen Pool. Derzeit werden randomisierte Round Robin- und Hashing-Methoden unterstützt.
create_pool
syntax: ok, err = api:create_pool(pool)
Erstellt einen neuen Pool aus einer Tabelle von Optionen, pool muss mindestens 1 Schlüssel id enthalten, der innerhalb des aktuellen Upstream-Objekts eindeutig sein muss.
Andere gültige Optionen sind
methodBalancing-MethodetimeoutVerbindungszeitüberschreitung in mspriorityHöhere Prioritätspools werden später verwendetread_timeoutkeepalive_timeoutkeepalive_poolstatus_codesSiehe status_codes
Hosts können an diesem Punkt nicht definiert werden.
Hinweis: IDs werden von dieser Funktion in einen String umgewandelt.
Standardpoolwerte
{ method = 'round_robin', timeout = 2000, priority = 0 }
set_priority
syntax: ok, err = api:set_priority(poolid, priority)
Die Priorität muss eine Zahl sein, gibt nil bei einem Fehler zurück.
add_host
syntax: ok, err = api:add_host(poolid, host)
Nimmt eine Pool-ID und eine Tabelle von Optionen, host muss mindestens host enthalten.
Wenn die Host-ID nicht angegeben ist, wird sie ein numerischer Index basierend auf der Anzahl der Hosts im Pool sein.
Hinweis: IDs werden von dieser Funktion in einen String umgewandelt.
Standardeinstellungen:
{ host = '', port = 80, weight = 0}
remove_host
syntax: ok, err = api:remove_host(poolid, host)
Nimmt eine poolid und eine hostid, um sie aus dem Pool zu entfernen.
down_host
syntax: ok,err = api:down_host(poolid, host)
Markiert einen Host manuell als down, dieser Host wird nicht automatisch wiederbelebt.
up_host
syntax: ok,err = api:up_host(poolid, host)
Stellt einen ausgefallenen Host manuell wieder im Pool her.
upstream.http
Funktionen zum Senden von HTTP-Anfragen an Upstream-Hosts.
new
syntax: httpc, err = upstream_http:new(upstream, ssl_opts?)
Gibt ein neues HTTP-Upstream-Objekt unter Verwendung des bereitgestellten Upstream-Objekts zurück.
ssl_opts ist eine optionale Tabelle zur Konfiguration der SSL-Unterstützung.
* ssl auf true setzen, um SSL-Handshake zu aktivieren, standardmäßig false
* ssl_verify auf false setzen, um die SSL-Zertifikatsüberprüfung zu deaktivieren, standardmäßig true
* sni_host ein String, der als SNI-Hostname verwendet wird, standardmäßig ist der Host-Header der Anfrage
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()
Initialisiert den Hintergrund-Thread, sollte in init_worker_by_lua aufgerufen werden.
Rufen Sie nicht die Methode init_background_thread in upstream.socket auf, wenn Sie den Hintergrund-Thread von upstream.http verwenden.
request
syntax: res, err_or_conn_info, status? = upstream_api:request(params)
Nimmt dieselben Parameter wie die request-Methode von lua-resty-http.
Bei einer erfolgreichen Anfrage gibt es das lua-resty-http-Objekt und eine Tabelle mit dem verbundenen Host und Pool zurück.
Wenn die Anfrage fehlgeschlagen ist, gibt es nil, den Fehler und einen vorgeschlagenen HTTP-Statuscode zurück.
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()
Leitet die Keepalive-Zeitüberschreitung / den Pool aus der Poolkonfiguration an die lua-resty-http set_keepalive-Methode weiter.
get_reused_times
syntax: ok, err = upstream_http:get_reused_times()
Leitet die lua-resty-http get_reused_times-Methode weiter.
close
syntax: ok, err = upstream_http:close()
Leitet die lua-resty-http close-Methode weiter.
HTTP-Gesundheitschecks
Aktive Hintergrund-Gesundheitschecks können aktiviert werden, indem der Parameter healthcheck zu einem Host hinzugefügt wird.
Ein Wert von true aktiviert die Standardprüfung, eine GET-Anfrage für /.
Der Parameter healthcheck kann auch eine Tabelle von Parametern sein, die für die request-Methode von lua-resty-http gültig sind.
Mit einigen zusätzlichen Parametern
interval, um die Zeit zwischen Gesundheitsprüfungen in Sekunden festzulegen. Muss >= 10s sein. Standardmäßig 60s.timeoutsetzt die Verbindungszeitüberschreitung für Gesundheitsprüfungen. Standardmäßig auf die Pool-Einstellung.read_timeoutsetzt die Lesezeitüberschreitung für Gesundheitsprüfungen. Standardmäßig auf die Pool-Einstellung.status_codeseine Tabelle ungültiger Antwortstatuscodes. Standardmäßig auf die Pool-Einstellung.
Das Scheitern der Hintergrundprüfung erfolgt nach denselben Parametern wie für eine Frontend-Anfrage, es sei denn, es wird ausdrücklich überschrieben.
-- Benutzerdefinierte Prüfparameter
api:add_host("primary", {
host = 123.123.123.123,
port = 80,
healthcheck = {
interval = 30, -- alle 30s prüfen
timeout = (5*1000), -- 5s Verbindungszeitüberschreitung
read_timeout = (15*1000), -- 15s Verbindungszeitüberschreitung
status_codes = {["5xx"] = true, ["403"] = true}, -- 5xx- und 403-Antworten sind ein Fehler
-- resty-http-Parameter
path = "/check",
headers = {
["Host"] = "domain.com",
["Accept-Encoding"] = "gzip"
}
}
})
-- Standardprüfparameter
api:add_host("primary", {host = 123.123.123.123, port = 80, healthcheck = true})
GitHub
Sie finden möglicherweise zusätzliche Konfigurationstipps und Dokumentationen für dieses Modul im GitHub-Repository für nginx-module-upstream.