checkups: Gérer les upstreams NGINX en Lua pur
Installation
Si vous n'avez pas configuré l'abonnement au dépôt RPM, inscrivez-vous. Ensuite, vous pouvez procéder avec les étapes suivantes.
CentOS/RHEL 7 ou 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-checkups
CentOS/RHEL 8+, Fedora Linux, Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install lua5.1-resty-checkups
Pour utiliser cette bibliothèque Lua avec NGINX, assurez-vous que nginx-module-lua est installé.
Ce document décrit lua-resty-checkups v0.1 publié le 1er février 2019.
- Envoi périodique de signaux de vie aux serveurs en amont
- Vérification de santé proactive et passive
- Mise à jour dynamique des upstreams
- Équilibrage par round-robin pondéré ou hachage cohérent
- Synchronisation avec les blocs upstream de Nginx
- Essayer des clusters par niveaux ou par clés
Synopsis
-- config.lua
_M = {}
_M.global = {
checkup_timer_interval = 15,
checkup_shd_sync_enable = true,
shd_config_timer_interval = 1,
}
_M.ups1 = {
cluster = {
{
servers = {
{ host = "127.0.0.1", port = 4444, weight=10, max_fails=3, fail_timeout=10 },
}
},
},
}
return _M
-- nginx.conf
lua_shared_dict state 10m;
lua_shared_dict mutex 1m;
lua_shared_dict locks 1m;
lua_shared_dict config 10m;
server {
listen 12350;
return 200 12350;
}
server {
listen 12351;
return 200 12351;
}
init_by_lua_block {
local config = require "config"
local checkups = require "resty.checkups.api"
checkups.init(config)
}
init_worker_by_lua_block {
local config = require "config"
local checkups = require "resty.checkups.api"
checkups.prepare_checker(config)
checkups.create_checker()
}
server {
location = /12350 {
proxy_pass http://127.0.0.1:12350/;
}
location = /12351 {
proxy_pass http://127.0.0.1:12351/;
}
location = /t {
content_by_lua_block {
local checkups = require "resty.checkups.api"
local callback = function(host, port)
local res = ngx.location.capture("/" .. port)
ngx.say(res.body)
return 1
end
local ok, err
-- se connecter à un serveur mort, aucun upstream disponible
ok, err = checkups.ready_ok("ups1", callback)
if err then ngx.say(err) end
-- ajouter un serveur à ups1
ok, err = checkups.update_upstream("ups1", {
{
servers = {
{ host = "127.0.0.1", port = 12350, weight=10, max_fails=3, fail_timeout=10 },
}
},
})
if err then ngx.say(err) end
ngx.sleep(1)
ok, err = checkups.ready_ok("ups1", callback)
if err then ngx.say(err) end
ok, err = checkups.ready_ok("ups1", callback)
if err then ngx.say(err) end
-- ajouter un serveur à un nouvel upstream
ok, err = checkups.update_upstream("ups2", {
{
servers = {
{ host="127.0.0.1", port=12351 },
}
},
})
if err then ngx.say(err) end
ngx.sleep(1)
ok, err = checkups.ready_ok("ups2", callback)
if err then ngx.say(err) end
-- ajouter un serveur à ups2, réinitialiser l'état rr
ok, err = checkups.update_upstream("ups2", {
{
servers = {
{ host = "127.0.0.1", port = 12350, weight=10, max_fails=3, fail_timeout=10 },
{ host = "127.0.0.1", port = 12351, weight=10, max_fails=3, fail_timeout=10 },
}
},
})
if err then ngx.say(err) end
ngx.sleep(1)
ok, err = checkups.ready_ok("ups2", callback)
if err then ngx.say(err) end
ok, err = checkups.ready_ok("ups2", callback)
if err then ngx.say(err) end
}
}
}
Une sortie typique de l'emplacement /t défini ci-dessus est :
no servers available
12350
12350
12351
12350
12351
Configuration
Configuration Lua
Le fichier de configuration des checkups est un module lua qui se compose de deux parties, la partie globale et la partie cluster.
Un exemple de fichier de configuration des checkups est montré ci-dessous,
-- config.lua
-- Voici la partie globale
_M = {}
_M.global = {
checkup_timer_interval = 15,
checkup_timer_overtime = 60,
default_heartbeat_enable = true,
checkup_shd_sync_enable = true,
shd_config_timer_interval = 1,
}
-- Les autres parties sont des configurations de cluster
_M.redis = {
enable = true,
typ = "redis",
timeout = 2,
read_timeout = 15,
send_timeout = 15,
protected = true,
cluster = {
{ -- niveau 1
try = 2,
servers = {
{ host = "192.168.0.1", port = 6379, weight=10, max_fails=3, fail_timeout=10 },
{ host = "192.168.0.2", port = 6379, weight=10, max_fails=3, fail_timeout=10 },
}
},
{ -- niveau 2
servers = {
{ host = "192.168.0.3", port = 6379, weight=10, max_fails=3, fail_timeout=10 },
}
},
},
}
_M.api = {
enable = false,
typ = "http",
http_opts = {
query = "GET /status HTTP/1.1\r\nHost: localhost\r\n\r\n",
statuses = {
["500"] = false,
["502"] = false,
["503"] = false,
["504"] = false,
},
},
mode = "hash",
cluster = {
dc1 = {
servers = {
{ host = "192.168.1.1", port = 1234, weight=10, max_fails=3, fail_timeout=10 },
}
},
dc2 = {
servers = {
{ host = "192.168.1.2", port = 1234, weight=10, max_fails=3, fail_timeout=10 },
}
}
}
}
_M.ups_from_nginx = {
timeout = 2,
cluster = {
{ -- niveau 1
upstream = "api.com",
},
{ -- niveau 2
upstream = "api.com",
upstream_only_backup = true,
},
},
}
return _M
configurations globales
checkup_timer_interval: Intervalle d'envoi des signaux de vie aux serveurs backend. La valeur par défaut est5.checkup_timer_overtime: Intervalle de vérifications pour expirer la clé de minuterie. Dans la plupart des cas, vous n'avez pas besoin de changer cette valeur. La valeur par défaut est60.default_heartbeat_enable: Les checkups enverront des signaux de vie aux serveurs par défaut ou non. La valeur par défaut esttrue.checkup_shd_sync_enable: Créer un synchroniseur d'upstream pour chaque worker. Si défini surfalse, l'upstream dynamique ne fonctionnera pas correctement. La valeur par défaut esttrue.shd_config_timer_interval: Intervalle de synchronisation de la liste des upstreams depuis la mémoire partagée. La valeur par défaut est égale àcheckup_timer_interval.ups_status_sync_enable: Si défini surtrue, les checkups synchroniseront l'état de l'upstream des checkups vers les blocs upstream de Nginx. La valeur par défaut estfalse.ups_status_timer_interval: Intervalle de synchronisation de l'état de l'upstream des checkups vers les blocs upstream de Nginx.
Configurations de cluster
skey:_M.xxxxx.xxxxxest laskey(clé de service) de ce cluster.enable: Activer ou désactiver les signaux de vie aux serveurs. La valeur par défaut esttrue.typ: Type de cluster, doit être l'un desgeneral,redis,mysql,http. La valeur par défaut estgeneral.general: Signal de vie par TCPsock:connect.redis: Signal de vie par redisPING. Le module lua-resty-redis est requis.mysql: Signal de vie par mysqldb:connect. Le module lua-resty-mysql est requis.http: Signal de vie par requête HTTP. Vous pouvez configurer des requêtes HTTP personnalisées et des codes de réponse danshttp_opts.
timeout: Délai de connexion aux serveurs upstream. La valeur par défaut est5.read_timeout: Délai de lecture pour les serveurs upstream (non utilisé lors de l'envoi de signaux de vie). La valeur par défaut est égale àtimeout.send_timeout: Délai d'écriture pour les serveurs upstream (non utilisé lors de l'envoi de signaux de vie). La valeur par défaut est égale àtimeout.-
http_opts: Configurations de signal de vie HTTP. Ne fonctionne que pourtyp="http".query: Requête HTTP pour le signal de vie.statuses: Si le code retourné par le serveur est défini surfalse, alors le serveur est considéré comme échouant.
-
mode: Mode d'équilibrage. Peut être défini surhash,url_hashouip_hash. Les checkups équilibreront les serveurs parhash_key,ngx.var.urioungx.var.remote_addr. La valeur par défaut estwrr. protected: Si défini surtrueet que tous les serveurs du cluster échouent, les checkups ne marqueront pas le dernier serveur échouant comme indisponible (err), mais il sera marqué commeinstable(toujours disponible lors de la prochaine tentative). La valeur par défaut esttrue.-
cluster: Vous pouvez configurer plusieurs niveaux selon la priorité du cluster, à chaque niveau vous pouvez configurer un cluster deservers. Les checkups essaieront le niveau suivant uniquement lorsque tous les serveurs du niveau précédent sont considérés comme indisponibles.Au lieu d'essayer des clusters par niveaux, vous pouvez configurer les checkups pour essayer des clusters par clé (voir le cluster
apici-dessus). N'oubliez pas que vous devez également passer un argument supplémentaire commeopts.cluster_key={"dc1", "dc2"}ouopts.cluster_key={3, 1, 2}à checkups.read_ok pour que les checkups essaient dans l'ordre dedc1,dc2ouniveau 3,niveau 1,niveau 2. Si vous n'avez pas passéopts.cluster_keyà checkups.ready_ok, les checkups essaieront toujours des clusters par niveaux. En ce qui concerne le clusterapici-dessus, les checkups retourneront finalementno servers available. *try: Nombre de tentatives. La valeur par défaut est le nombre de serveurs. *try_timeout: Limite le temps pendant lequel une requête peut être répondue, de même quenginx proxy_next_upstream_timeout. *servers: La configuration pourserversest listée comme suit, *weight: Définit le poids du serveur. La valeur par défaut est1. *max_fails: Définit le nombre de tentatives infructueuses de communication avec le serveur qui doivent se produire dans la durée définie par le paramètrefail_timeout. Par défaut, le nombre de tentatives infructueuses est défini sur0, ce qui désactive le comptage des tentatives. Ce qui est considéré comme une tentative infructueuse est défini parhttp_opts.statusessityp="http"ou unnil/falseretourné par checkups.ready_ok. Cette option n'est disponible qu'en round-robin. *fail_timeout: Définit le temps pendant lequel le nombre spécifié de tentatives infructueuses de communication avec le serveur doit se produire pour considérer le serveur comme indisponible et la période pendant laquelle le serveur sera considéré comme indisponible. Par défaut, le paramètre est défini sur10secondes. Cette option n'est disponible qu'en round-robin.upstream: Nom des blocs upstream Nginx. Les checkups extrairont les serveurs des blocs upstream de la configuration Nginx dans prepare_checker. Le module lua-upstream-nginx-module est requis.upstream_only_backup: Si défini surtrue, les checkups n'extraireont que les serveurs de secours des blocs upstream Nginx.
Configuration Nginx
Ajoutez les chemins du fichier de configuration lua et des checkups à lua_package_path et créez des dictionnaires partagés lua utilisés par les checkups. Vous devriez mettre ces lignes dans le bloc http de votre fichier de configuration Nginx.
lua_shared_dict state 10m;
lua_shared_dict mutex 1m;
lua_shared_dict locks 1m;
lua_shared_dict config 10m;
Si vous utilisez le sous-système de flux, vous devez mettre ces lignes dans le bloc stream de votre fichier de configuration Nginx.
lua_shared_dict stream_state 10m;
lua_shared_dict stream_mutex 1m;
lua_shared_dict stream_locks 1m;
lua_shared_dict stream_config 10m;
API

init
syntax: init(config)
phase: init_by_lua
Copie des upstreams depuis config.lua vers shdict, extrait les serveurs des blocs upstream Nginx et effectue quelques initialisations de base.
prepare_checker
syntax: prepare_checker(config)
phase: init_worker_by_lua
Copie les configurations depuis config.lua vers les checkups des workers, extrait les serveurs des blocs upstream Nginx et effectue quelques initialisations de base.
create_checker
syntax: create_checker()
phase: init_worker_by_lua
Crée un minuteur de signal de vie et un minuteur de synchronisation des upstreams. Un seul minuteur de signal de vie sera créé parmi tous les workers. Il est fortement recommandé d'appeler cette méthode dans la phase init_worker.
ready_ok
syntax: res, err = ready_ok(skey, callback, opts?)
phase: rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*
Sélectionne un peer disponible du cluster skey et appelle callback(peer.host, peer.port, opts).
La table opts accepte les champs suivants,
cluster_key: Essayer des clusters parcluster_key. Les checkups essaieront des clusters dans l'ordre decluster_key.clusters_keypeut être le nom des clusters ou le niveau des clusters. clusters ex:{"cluster_name_A", "name_B", "name_C"}. niveaux ex:{3, 2, 1}.hash_key: Clé utilisée dans le mode d'équilibragehash. Si non défini,ngx.var.urisera utilisé.try: Le nombre de tentatives ne sera pas supérieur àtry.try_timeout: Limite le temps pendant lequel une requête peut être répondue, de même quenginx proxy_next_upstream_timeout.
Retourne ce que callback retourne en cas de succès, ou retourne nil et une chaîne décrivant l'erreur sinon.
Si callback retourne nil ou false, les checkups considéreront cela comme une tentative échouée et réessaieront callback avec un autre peer. Donc, rappelez-vous toujours de ne pas retourner nil ou false après un callback réussi.
select_peer
syntax: peer, err = select_peer(skey)
context: rewrite_by_lua*, access_by_lua*, content_by_lua*, balancer_by_lua
Sélectionne un peer disponible du cluster skey.
Retourne une table contenant host et port d'un peer disponible.
En cas d'erreurs, retourne nil avec une chaîne décrivant l'erreur.
get_status
syntax: status = get_status()
phase: rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*
Retourne l'état des checkups au format json.
get_ups_timeout
syntax: connect_timeout, send_timeout, read_timeout = get_ups_timeout(skey)
phase: rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*
Retourne le délai d'attente du cluster skey.
feedback_status
syntax: ok, err = feedback_status(skey, host, port, failed)
context: rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, balancer_by_lua.*
Marque le serveur host:port dans le cluster skey comme échoué (true) ou disponible (false).
Retourne 1 en cas de succès, ou retourne nil et une chaîne décrivant l'erreur sinon.
update_upstream
syntax: ok, err = update_upstream(skey, upstream)
phase: rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*
Met à jour le cluster skey. upstream est au même format que cluster dans config.lua.
Retourne true en cas de succès, ou retourne false et une chaîne décrivant l'erreur sinon.
delete_upstream
syntax: ok, err = delete_upstream(skey)
phase: rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*
Supprime le cluster skey de la liste des upstreams.
Retourne true en cas de succès, ou retourne false et une chaîne décrivant l'erreur sinon.
Voir aussi
GitHub
Vous pouvez trouver des conseils de configuration supplémentaires et de la documentation pour ce module dans le dépôt GitHub pour nginx-module-checkups.