SLB est un équilibreur de charge sans session pour le trafic UDP et résout les problèmes inhérents à l'utilisation d'équilibreurs de charge traditionnels (riches en fonctionnalités) pour un tel trafic.
Pour les protocoles UDP simples et sans état, il n'y a aucun avantage à essayer de maintenir une « affinité » (c'est-à-dire des « sessions ») entre les clients et les instances back-end. Les équilibreurs de charge traditionnels supposent que l'affinité est utile et tentent donc d'acheminer les paquets d'un client vers un serveur back-end cohérent. En revanche, SLB distribue uniformément (aléatoirement) les paquets un par un sur tous les back-ends disponibles. Cela se traduit par un chargement uniforme des backends et une robustesse améliorée en cas de panne d'une instance backend (il y aura une augmentation de la perte de paquets pour tous les clients plutôt qu'une perte totale de trafic pour certains clients).
Par défaut, SLB écoutera sur les ports 1812
et 1813
les paquets UDP entrants et les relayera vers des cibles backend aléatoires qu'il connaît. Les ports sur lesquels il écoute peuvent utiliser l'option --server-port-range
, qui accepte un seul port (par exemple 541
) ou une plage de ports (par exemple 4000-5000
).
Pour que SLB soit conscient des backends, il faut envoyer des paquets « chien de garde » (alias « garder en vie ») au port admin (plus d'informations à ce sujet ci-dessous). Par défaut, le port admin est 1111
, mais il peut être configuré à l'aide de l'option --admin-port
. Si plusieurs cartes réseau sont présentes dans votre système, vous pouvez spécifier l'adresse IP à l'aide de l'option --admin-ip
. Si l'adresse IP spécifiée avec --admin-ip
se trouve dans la plage CIDR de multidiffusion ( 244.0.0.0/4
), SLB rejoindra automatiquement ce groupe de multidiffusion (plus d'informations ci-dessous).
D'autres options sont décrites dans l'aide de la commande :
SimplestLoadBalancer:
Sessionless UDP Load Balancer sends packets to backends without session affinity.
Usage:
SimplestLoadBalancer [options]
Options:
--server-port-range <server-port-range> Set the ports to listen to and forward to backend targets
(default "1812-1813") [default: 1812-1813]
--admin-ip <admin-ip> Set the IP to listen on for watchdog events [default is first private IP]
--admin-port <admin-port> Set the port that targets will send watchdog events [default: 1111]
--client-timeout <client-timeout> Seconds to allow before cleaning-up idle clients [default: 30]
--target-timeout <target-timeout> Seconds to allow before removing target missing watchdog events [default: 30]
--default-target-weight <default-target-weight> Weight to apply to targets when not specified [default: 100]
--unwise Allows public IP addresses for targets [default: False]
--stats-period-ms <stats-period-ms> Sets the number of milliseconds between statistics messages printed to the
console (disable: 0, max: 65535) [default: 1000]
--default-group-id <default-group-id> Sets the group ID to assign to backends that when a registration packet doesn't
include one, and when port isn't assigned a group [default: 0]
--version Show version information
-?, -h, --help Show help and usage information
Les backends ne sont pas configurés sur la ligne de commande. Au lieu de cela, ils sont enregistrés et désenregistrés dynamiquement à l'aide de paquets UDP périodiques envoyés au port d'administration ( --admin-port
). Le contenu de ces paquets peut différer en fonction de la manière dont vous utilisez SLB dans votre environnement.
Si vous utilisez un seul serveur SLB, les backends peuvent être configurés pour envoyer des paquets à cette adresse IP et sur le port d'administration. C'est le scénario le plus simple. Chaque backend enverra des messages avec deux « octets magiques » pour indiquer « l'enregistrement du backend » pour le contenu :
0x11 0x11
SLB interprétera un tel paquet comme « enregistrer l'expéditeur en tant que backend ». Facultativement, les messages peuvent contenir un ou deux octets supplémentaires (poids et identifiant de groupe) dont le but sera discuté plus en détail ci-dessous.
0x11 0x11 [X] [X]
^ ^
| |
| one byte for group id
|
one byte for weight
Dans certains environnements, les paquets d'enregistrement ne seront pas envoyés depuis les backends eux-mêmes, et SLB prend en charge de tels cas d'utilisation. Lorsqu'un paquet d'enregistrement est envoyé par un « tiers », le contenu devra inclure l'adresse IP du backend en cours d'enregistrement :
0x11 0x11 X X X X [X] [X]
^ ^ ^
| | |
| | one byte for group id
| |
| one byte for weight
|
four bytes for ip to add
Là encore, les octets de poids et d'identification de groupe peuvent éventuellement être ajoutés.
Lorsqu'un déploiement HA plus robuste avec plusieurs SLB est nécessaire, la communication entre les backends et le SLB peut être simplifiée en utilisant une adresse IP de groupe de multidiffusion. Ceci est utile puisque chaque SLB doit connaître chaque backend. Dans un tel cas, les serveurs SLB doivent utiliser l'option --admin-ip
pour spécifier une adresse de multidiffusion qui amènera les SLB à rejoindre le groupe de multidiffusion et donc à recevoir tous les messages envoyés à cette adresse IP. Les backends peuvent être configurés avec cette seule adresse IP, minimisant leur charge de travail et simplifiant leur configuration (en particulier lorsque les SLB sont mis en service et hors service en raison de la mise à l'échelle automatique et/ou de l'utilisation d'instances ponctuelles).
Notez que l'utilisation d'une IP de multidiffusion nécessite soit un commutateur prenant en charge la multidiffusion, soit (plus probablement) exécuté dans un AWS VPC configuré avec un domaine de multidiffusion.
Les formats des paquets d'administration sont très simples à partir de la version 2.0. Dans le cas d'utilisation le plus simple d'un seul SLB, un paquet d'enregistrement provenant d'un backend ne peut contenir que deux octets magiques ( 0x11
0x11
). En option, les paquets peuvent provenir d'une source différente (par exemple un serveur de gestion) et inclure quatre octets pour spécifier l'adresse IPv4 d'un backend. Dans les deux cas, deux octets facultatifs supplémentaires pour le « poids » du trafic par rapport aux autres backends et pour le « groupe » à attribuer au backend peuvent être ajoutés (plus d’informations sur les groupes ci-dessous). En art ASCII :
0x11 0x11 [X X X X] [X] [X]
^ ^ ^
| | |
| | one byte for group id
| |
| one byte for weight
|
four bytes for ip to add
Pour supprimer immédiatement une cible, envoyez un paquet avec 0x86
comme premier octet au lieu de 0x11
(s'il est envoyé depuis un serveur de gestion, ajoutez l'adresse IP du backend à supprimer) :
0x86 0x11 [X X X X]
^
|
four bytes for ip to remove
Les pondérations sont utilisées pour contrôler la quantité relative de trafic délivrée à chaque backend. Si aucun poids n'est spécifié, la valeur par défaut de 100 (configurable avec --default-target-weight
) sera appliquée au backend, et chacun recevra le même volume de paquets. Cela dit, il est attendu (et conseillé) que les backends ajustent la valeur de poids dans leurs paquets d'administration en fonction de leur capacité à gérer le trafic (peut-être réduit lorsque le processeur est élevé, que des mises à jour sont appliquées, etc.). Par exemple:
100
, 50
et 50
respectivement, alors le premier recevra 50 % du trafic et le deuxième et le troisième recevront chacun 25 %.31
et 31
, chacun recevra 50 % du trafic.Lors de l'utilisation de groupes, les poids relatifs sont évalués par rapport aux autres backends du même groupe (pas dans tous les groupes).
Il est important d'envoyer les paquets d'administration de manière fiable et à une cadence suffisante. Chaque fois qu'un paquet est reçu par SLB, l'heure de « dernière vue » du backend est mise à jour. Si 30 secondes (configurables avec
--target-timeout
) s'écoulent sans qu'un backend soit vu, il est supprimé et aucun autre trafic ne lui sera envoyé.
Par défaut, tous les backends seront utilisés pour desservir tous les ports desservis par l'équilibreur de charge.
Cependant, il est possible d'attribuer des ports individuels à des sous-ensembles de backends à l'aide de messages d'attribution de port SLB et en fournissant des ID de groupe dans les messages d'enregistrement. Considérez, par exemple, que vous souhaitez équilibrer la charge SLB pour les ports 1812 et 1813, mais attribuer le trafic atteignant chaque port à un ensemble différent de serveurs. Pour ce faire :
x66 x11
) avec un numéro de port (deux octets) et un ID de groupe (un octet). Ces messages n'ont pas besoin d'être répétés et peuvent être envoyés lorsqu'une modification des attributions de groupes de ports est souhaitée (il n'y a aucun mal à les répéter, cependant, ce qui peut être pratique pour garantir que les ports sont correctement attribués aux groupes après le redémarrage du service). 0x66 0x11 X X X
^ ^
| |
| one byte for group ID
|
two bytes for port number, litten endian
En utilisant Linux bash
il est simple d'envoyer des paquets d'administration. Cela peut être fait à l'aide de la commande netcat
(alias. nc
) ou du système de fichiers /dev/udp
. Par exemple, si votre équilibreur de charge écoute sur le port admin par défaut 1111
et que vous souhaitez ajouter une cible avec l'IP 192.168.1.22
:
$ echo -e $( echo " x11x11 $( echo " 192.168.1.22 " | tr " . " " n " | xargs printf ' \x%02X ' ) " ) > /dev/udp/127.0.0.1/1111
Puisqu'il peut être fastidieux d'envoyer manuellement ces paquets pour conserver un ensemble de cibles enregistrées, vous pouvez créer un petit script shell, par exemple lb.sh
:
#! /bin/bash
echo -ne $( echo " x11x11 $( echo " 192.168.1.22 " | tr " . " " n " | xargs printf ' \x%02X ' ) " ) > /dev/udp/127.1.1.1/1111
echo -ne $( echo " x11x11 $( echo " 192.168.1.23 " | tr " . " " n " | xargs printf ' \x%02X ' ) " ) > /dev/udp/127.1.1.1/1111
echo -ne $( echo " x11x11 $( echo " 192.168.1.24 " | tr " . " " n " | xargs printf ' \x%02X ' ) " ) > /dev/udp/127.1.1.1/1111
echo -ne $( echo " x11x11 $( echo " 192.168.1.25 " | tr " . " " n " | xargs printf ' \x%02X ' ) " ) > /dev/udp/127.1.1.1/1111
echo -ne $( echo " x11x11 $( echo " 192.168.1.26 " | tr " . " " n " | xargs printf ' \x%02X ' ) " ) > /dev/udp/127.1.1.1/1111
echo -ne $( echo " x11x11 $( echo " 192.168.1.27 " | tr " . " " n " | xargs printf ' \x%02X ' ) " ) > /dev/udp/127.1.1.1/1111
Et puis utilisez la commande watch
pour appeler ce script toutes les quelques secondes :
$ watch -n10 ./lb.sh
Des binaires prédéfinis pour Linux, Windows x64 et Linux ARM sont disponibles sous forme de « versions » de GitHub. Il s'agit d'un projet .Net 8.0 très simple, donc pour le construire, exécutez (en supposant que dotnet-sdk-8.0 soit installé) :
dotnet build
Vous souhaiterez probablement générer un exécutable binaire natif, ce qui est pratique et offre certains avantages en termes de performances.
Pour Linux :
dotnet publish -o ./ -c Release -r linux-x64 /p:PublishSingleFile=true /p:PublishTrimmed=true --self-contained
Pour Windows :
dotnet publish -o ./ -c Release -r win10-x64 /p:PublishSingleFile=true /p:PublishTrimmed=true --self-contained
De même, il est simple à exécuter en utilisant dotnet run
dans le répertoire du projet :
$ dotnet run
Ou, si vous avez créé un exécutable natif :
$ ./SimplestLoadBalancer
N'hésitez pas à créer des problèmes ici sur GitHub pour des questions et des rapports de bogues. Aucun modèle n'est fourni ni aucune exigence, mais veuillez essayer d'être aussi descriptif que possible - cela nous aidera à garantir que nous sommes en mesure de répondre de manière sensée. Voir aussi, contribuer.
Apprécier!