Vereinfachtes NGINX-Load-Balancing mit Loadcat
Veröffentlicht: 2022-03-11Webanwendungen, die auf horizontale Skalierbarkeit ausgelegt sind, erfordern häufig einen oder mehrere Lastausgleichsknoten. Ihr Hauptzweck besteht darin, den eingehenden Datenverkehr fair auf verfügbare Webserver zu verteilen. Die Möglichkeit, die Gesamtkapazität einer Webanwendung zu erhöhen, indem einfach die Anzahl der Knoten erhöht wird und sich die Load Balancer an diese Änderung anpassen, kann sich in der Produktion als äußerst nützlich erweisen.
NGINX ist ein Webserver, der neben vielen anderen Funktionen leistungsstarke Load-Balancing-Funktionen bietet. Einige dieser Funktionen sind nur als Teil ihres Abonnementmodells verfügbar, aber die kostenlose und Open-Source-Version ist immer noch sehr funktionsreich und verfügt über die wichtigsten Load-Balancing-Funktionen.
In diesem Tutorial werden wir die inneren Mechanismen eines experimentellen Tools untersuchen, mit dem Sie Ihre NGINX-Instanz im Handumdrehen so konfigurieren können, dass sie als Load Balancer fungiert und alle wesentlichen Details der NGINX-Konfigurationsdateien abstrahiert, indem Sie eine übersichtliche Web- basierte Benutzeroberfläche. Der Zweck dieses Artikels ist es, zu zeigen, wie einfach es ist, mit der Erstellung eines solchen Tools zu beginnen. Es ist erwähnenswert, dass das Projekt Loadcat stark von Linodes NodeBalancern inspiriert ist.
NGINX, Server und Upstreams
Eine der beliebtesten Anwendungen von NGINX ist das Reverse-Proxying von Anfragen von Clients an Webserver-Anwendungen. Obwohl in Programmiersprachen wie Node.js und Go entwickelte Webanwendungen autarke Webserver sein können, bietet ein Reverse-Proxy vor der eigentlichen Serveranwendung zahlreiche Vorteile. Ein „Server“-Block für einen einfachen Anwendungsfall wie diesen in einer NGINX-Konfigurationsdatei kann etwa so aussehen:
server { listen 80; server_name example.com; location / { proxy_pass http://192.168.0.51:5000; } }
Dies würde NGINX veranlassen, Port 80 auf alle Anfragen zu überwachen, die auf example.com verweisen, und jede von ihnen an eine Webserveranwendung weiterzuleiten, die unter 192.168.0.51:5000 ausgeführt wird. Wir könnten hier auch die Loopback-IP-Adresse 127.0.0.1 verwenden, wenn der Webanwendungsserver lokal ausgeführt wird. Bitte beachten Sie, dass dem obigen Snippet einige offensichtliche Optimierungen fehlen, die häufig in der Reverse-Proxy-Konfiguration verwendet werden, aber der Kürze halber so beibehalten werden.
Aber was wäre, wenn wir alle eingehenden Anfragen zwischen zwei Instanzen desselben Webanwendungsservers ausgleichen wollten? Hier wird die „Upstream“-Direktive nützlich. In NGINX ist es mit der „Upstream“-Direktive möglich, mehrere Back-End-Knoten zu definieren, unter denen NGINX alle eingehenden Anfragen ausgleicht. Zum Beispiel:
upstream nodes { server 192.168.0.51:5000; server 192.168.0.52:5000; } server { listen 80; server_name example.com; location / { proxy_pass http://nodes; } }
Beachten Sie, wie wir einen „Upstream“-Block namens „nodes“ definiert haben, der aus zwei Servern besteht. Jeder Server wird durch eine IP-Adresse und die Portnummer, auf der er lauscht, identifiziert. Damit wird NGINX zum Load Balancer in seiner einfachsten Form. Standardmäßig verteilt NGINX eingehende Anfragen im Round-Robin-Verfahren, wobei die erste an den ersten Server weitergeleitet wird, die zweite an den zweiten Server, die dritte an den ersten Server und so weiter.
Allerdings hat NGINX noch viel mehr zu bieten, wenn es um Load Balancing geht. Es ermöglicht Ihnen, Gewichtungen für jeden Server zu definieren, sie als vorübergehend nicht verfügbar zu markieren, einen anderen Ausgleichsalgorithmus auszuwählen (z. B. gibt es einen, der auf der Grundlage des IP-Hashs des Clients funktioniert) usw. Diese Funktionen und Konfigurationsanweisungen sind alle schön dokumentiert auf nginx.org . Darüber hinaus ermöglicht NGINX das fast unterbrechungsfreie Ändern und Neuladen von Konfigurationsdateien im laufenden Betrieb.
Die Konfigurierbarkeit und die einfachen Konfigurationsdateien von NGINX machen es wirklich einfach, es an viele Bedürfnisse anzupassen. Und im Internet gibt es bereits eine Fülle von Tutorials, die Ihnen genau beibringen, wie Sie NGINX als Load Balancer konfigurieren.
Loadcat: NGINX-Konfigurationstool
Es gibt etwas Faszinierendes an Programmen, die, anstatt etwas selbst zu tun, andere Tools konfigurieren, um es für sie zu tun. Sie tun nicht wirklich viel, außer vielleicht Benutzereingaben zu nehmen und ein paar Dateien zu generieren. Die meisten Vorteile, die Sie aus diesen Tools ziehen, sind tatsächlich Funktionen anderer Tools. Aber sie machen das Leben auf jeden Fall einfacher. Beim Versuch, einen Load Balancer für eines meiner eigenen Projekte einzurichten, fragte ich mich: Warum nicht etwas Ähnliches für NGINX und seine Load-Balancing-Funktionen tun?
Loadcat war geboren!
Loadcat, gebaut mit Go, steckt noch in den Kinderschuhen. Im Moment erlaubt Ihnen das Tool, NGINX nur für den Lastenausgleich und die SSL-Beendigung zu konfigurieren. Es bietet dem Benutzer eine einfache webbasierte GUI. Anstatt durch einzelne Funktionen des Tools zu gehen, lassen Sie uns einen Blick auf das werfen, was sich darunter befindet. Beachten Sie jedoch, dass jemand, der gerne mit NGINX-Konfigurationsdateien von Hand arbeitet, in einem solchen Tool möglicherweise wenig Wert findet.
Es gibt einige Gründe dafür, Go als Programmiersprache dafür zu wählen. Einer davon ist, dass Go kompilierte Binärdateien erzeugt. Auf diese Weise können wir Loadcat als kompilierte Binärdatei auf Remote-Servern erstellen und verteilen oder bereitstellen, ohne uns Gedanken über die Auflösung von Abhängigkeiten machen zu müssen. Etwas, das den Einrichtungsprozess erheblich vereinfacht. Natürlich geht die Binärdatei davon aus, dass NGINX bereits installiert ist und eine systemd-Unit-Datei dafür existiert.
Falls Sie kein Go-Ingenieur sind, machen Sie sich keine Sorgen. Go ist recht einfach und macht Spaß, damit anzufangen. Darüber hinaus ist die Implementierung selbst sehr einfach und Sie sollten leicht nachvollziehen können.
Struktur
Go-Build-Tools erlegen ein paar Einschränkungen auf, wie Sie Ihre Anwendung strukturieren können, und überlassen den Rest dem Entwickler. In unserem Fall haben wir die Dinge je nach Zweck in ein paar Go-Pakete aufgeteilt:
- cfg: lädt, analysiert und stellt Konfigurationswerte bereit
- cmd/loadcat: Hauptpaket, enthält den Einstiegspunkt, kompiliert in Binärdatei
- Daten: enthält „Modelle“, verwendet einen eingebetteten Schlüssel/Wert-Speicher für die Persistenz
- feline: enthält Kernfunktionalität, z. B. Generierung von Konfigurationsdateien, Reload-Mechanismus usw.
- ui: Enthält Vorlagen, URL-Handler usw.
Wenn wir uns die Paketstruktur genauer ansehen, insbesondere innerhalb des feline-Pakets, werden wir feststellen, dass der gesamte NGINX-spezifische Code in einem Unterpaket feline/nginx aufbewahrt wurde. Dies geschieht, damit wir den Rest der Anwendungslogik generisch halten und die Unterstützung für andere Load Balancer (z. B. HAProxy) in Zukunft erweitern können.
Einstiegspunkt
Beginnen wir mit dem Hauptpaket für Loadcat, das sich in „cmd/loadcatd“ befindet. Die Hauptfunktion, Einstiegspunkt der Anwendung, macht drei Dinge.
func main() { fconfig := flag.String("config", "loadcat.conf", "") flag.Parse() cfg.LoadFile(*fconfig) feline.SetBase(filepath.Join(cfg.Current.Core.Dir, "out")) data.OpenDB(filepath.Join(cfg.Current.Core.Dir, "loadcat.db")) defer data.DB.Close() data.InitDB() http.Handle("/api", api.Router) http.Handle("/", ui.Router) go http.ListenAndServe(cfg.Current.Core.Address, nil) // Wait for an “interrupt“ signal (Ctrl+C in most terminals) }
Um die Dinge einfach zu halten und den Code leichter lesbar zu machen, wurde der gesamte Fehlerbehandlungscode aus dem obigen Ausschnitt entfernt (und auch aus den Ausschnitten später in diesem Artikel).
Wie Sie dem Code entnehmen können, laden wir die Konfigurationsdatei basierend auf dem Befehlszeilen-Flag „-config“ (das standardmäßig „loadcat.conf“ im aktuellen Verzeichnis ist). Als nächstes initialisieren wir ein paar Komponenten, nämlich das feline Kernpaket und die Datenbank. Schließlich starten wir einen Webserver für die webbasierte GUI.
Aufbau
Das Laden und Analysieren der Konfigurationsdatei ist hier wahrscheinlich der einfachste Teil. Wir verwenden TOML, um Konfigurationsinformationen zu codieren. Für Go ist ein nettes TOML-Parsing-Paket verfügbar. Wir benötigen nur sehr wenige Konfigurationsinformationen vom Benutzer, und in den meisten Fällen können wir vernünftige Standardwerte für diese Werte ermitteln. Die folgende Struktur stellt die Struktur der Konfigurationsdatei dar:
struct { Core struct { Address string Dir string Driver string } Nginx struct { Mode string Systemd struct { Service string } } }
Und so könnte eine typische „loadcat.conf“-Datei aussehen:
[core] address=":26590" dir="/var/lib/loadcat" driver="nginx" [nginx] mode="systemd" [nginx.systemd] service="nginx.service"
Wie wir sehen können, gibt es eine Ähnlichkeit zwischen der Struktur der TOML -codierten Konfigurationsdatei und der darüber gezeigten Struktur. Das Konfigurationspaket beginnt mit dem Festlegen einiger vernünftiger Standardwerte für bestimmte Felder der Struktur und parst dann die Konfigurationsdatei darüber. Falls es keine Konfigurationsdatei im angegebenen Pfad findet, erstellt es eine und speichert zuerst die Standardwerte darin.
func LoadFile(name string) error { f, _ := os.Open(name) if os.IsNotExist(err) { f, _ = os.Create(name) toml.NewEncoder(f).Encode(Current) f.Close() return nil } toml.NewDecoder(f).Decode(&Current) return nil }
Daten und Persistenz
Treffen Sie Bolt. Ein eingebetteter Schlüssel/Wert-Speicher, der in reinem Go geschrieben ist. Es wird als Paket mit einer sehr einfachen API geliefert, unterstützt Transaktionen sofort und ist beunruhigend schnell.
Innerhalb der Paketdaten haben wir Strukturen , die jeden Entitätstyp darstellen. Wir haben zum Beispiel:
type Balancer struct { Id bson.ObjectId Label string Settings BalancerSettings } type Server struct { Id bson.ObjectId BalancerId bson.ObjectId Label string Settings ServerSettings }
… wobei eine Instanz von Balancer einen einzelnen Load Balancer darstellt. Loadcat ermöglicht es Ihnen effektiv, Anforderungen für mehrere Webanwendungen über eine einzige Instanz von NGINX auszugleichen. Jeder Balancer kann dann einen oder mehrere Server dahinter haben, wobei jeder Server ein separater Back-End-Knoten sein kann.
Da Bolt ein Schlüsselwertspeicher ist und keine erweiterten Datenbankabfragen unterstützt, haben wir eine anwendungsseitige Logik, die dies für uns erledigt. Loadcat ist nicht dazu gedacht, Tausende von Balancern mit Tausenden von Servern in jedem von ihnen zu konfigurieren, daher funktioniert dieser naive Ansatz natürlich gut. Außerdem arbeitet Bolt mit Schlüsseln und Werten, die Byte-Slices sind, und deshalb codieren wir die Strukturen BSON, bevor wir sie in Bolt speichern. Die Implementierung einer Funktion, die eine Liste von Balancer-Strukturen aus der Datenbank abruft, ist unten dargestellt:
func ListBalancers() ([]Balancer, error) { bals := []Balancer{} DB.View(func(tx *bolt.Tx) error { b := tx.Bucket([]byte("balancers")) c := b.Cursor() for k, v := c.First(); k != nil; k, v = c.Next() { bal := Balancer{} bson.Unmarshal(v, &bal) bals = append(bals, bal) } return nil }) return bals, nil }
Die ListBalancers -Funktion startet eine schreibgeschützte Transaktion, iteriert über alle Schlüssel und Werte im „Balancers“-Bucket, dekodiert jeden Wert in eine Instanz der Balancer -Struktur und gibt sie in einem Array zurück.

Die Aufbewahrung eines Balancers im Eimer ist fast genauso einfach:
func (l *Balancer) Put() error { if !l.Id.Valid() { l.Id = bson.NewObjectId() } if l.Label == "" { l.Label = "Unlabelled" } if l.Settings.Protocol == "https" { // Parse certificate details } else { // Clear fields relevant to HTTPS only, such as SSL options and certificate details } return DB.Update(func(tx *bolt.Tx) error { b := tx.Bucket([]byte("balancers")) p, err := bson.Marshal(l) if err != nil { return err } return b.Put([]byte(l.Id.Hex()), p) }) }
Die Put -Funktion weist bestimmten Feldern einige Standardwerte zu, analysiert das angehängte SSL-Zertifikat im HTTPS-Setup, startet eine Transaktion, codiert die Struct -Instanz und speichert sie im Bucket mit der ID des Balancers.
Beim Analysieren des SSL-Zertifikats werden zwei Informationen mithilfe der Standardpaketverschlüsselung/pem extrahiert und in SSLOptions im Feld Einstellungen gespeichert: die DNS-Namen und der Fingerabdruck.
Wir haben auch eine Funktion, die Server nach Balancer sucht:
func ListServersByBalancer(bal *Balancer) ([]Server, error) { srvs := []Server{} DB.View(func(tx *bolt.Tx) error { b := tx.Bucket([]byte("servers")) c := b.Cursor() for k, v := c.First(); k != nil; k, v = c.Next() { srv := Server{} bson.Unmarshal(v, &srv) if srv.BalancerId.Hex() != bal.Id.Hex() { continue } srvs = append(srvs, srv) } return nil }) return srvs, nil }
Diese Funktion zeigt, wie naiv unser Ansatz wirklich ist. Hier lesen wir effektiv den gesamten „Server“-Bucket und filtern die irrelevanten Entitäten heraus, bevor wir das Array zurückgeben. Aber andererseits funktioniert das ganz gut, und es gibt keinen wirklichen Grund, es zu ändern.
Die Put -Funktion für Server ist viel einfacher als die Balancer -Struktur, da sie nicht so viele Codezeilen für Standardeinstellungen und berechnete Felder erfordert.
Steuerung von NGINX
Vor der Verwendung von Loadcat müssen wir NGINX konfigurieren, um die generierten Konfigurationsdateien zu laden. Loadcat generiert die Datei „nginx.conf“ für jeden Balancer in einem Verzeichnis nach der ID des Balancers (eine kurze Hex-Zeichenfolge). Diese Verzeichnisse werden unter einem „out“-Verzeichnis bei cwd
. Daher ist es wichtig, dass Sie NGINX so konfigurieren, dass diese generierten Konfigurationsdateien geladen werden. Dies kann mit einer „include“-Direktive innerhalb des „http“-Blocks erfolgen:
Bearbeiten Sie /etc/nginx/nginx.conf und fügen Sie die folgende Zeile am Ende des „http“-Blocks hinzu:
http { include /path/to/out/*/nginx.conf; }
Dies veranlasst NGINX, alle unter „/path/to/out/“ gefundenen Verzeichnisse zu scannen, in jedem Verzeichnis nach Dateien mit dem Namen „nginx.conf“ zu suchen und jede gefundene Datei zu laden.
In unserem Kernpaket feline definieren wir eine Schnittstelle Driver . Jede Struktur , die zwei Funktionen, Generate und Reload , mit der richtigen Signatur bereitstellt, qualifiziert sich als Treiber.
type Driver interface { Generate(string, *data.Balancer) error Reload() error }
Zum Beispiel die Struktur Nginx unter den Paketen feline/nginx:
type Nginx struct { sync.Mutex Systemd *dbus.Conn } func (n Nginx) Generate(dir string, bal *data.Balancer) error { // Acquire a lock on n.Mutex, and release before return f, _ := os.Create(filepath.Join(dir, "nginx.conf")) TplNginxConf.Execute(f, /* template parameters */) f.Close() if bal.Settings.Protocol == "https" { // Dump private key and certificate to the output directory (so that Nginx can find them) } return nil } func (n Nginx) Reload() error { // Acquire a lock on n.Mutex, and release before return switch cfg.Current.Nginx.Mode { case "systemd": if n.Systemd == nil { c, err := dbus.NewSystemdConnection() n.Systemd = c } ch := make(chan string) n.Systemd.ReloadUnit(cfg.Current.Nginx.Systemd.Service, "replace", ch) <-ch return nil default: return errors.New("unknown Nginx mode") } }
Generate kann mit einem String aufgerufen werden, der den Pfad zum Ausgabeverzeichnis und einen Zeiger auf eine Balancer -Strukturinstanz enthält. Go bietet ein Standardpaket für Textvorlagen, das der NGINX-Treiber verwendet, um die endgültige NGINX-Konfigurationsdatei zu generieren. Die Vorlage besteht aus einem „Upstream“-Block, gefolgt von einem „Server“-Block, der basierend auf der Konfiguration des Balancers generiert wird:
var TplNginxConf = template.Must(template.New("").Parse(` upstream {{.Balancer.Id.Hex}} { {{if eq .Balancer.Settings.Algorithm "least-connections"}} least_conn; {{else if eq .Balancer.Settings.Algorithm "source-ip"}} ip_hash; {{end}} {{range $srv := .Balancer.Servers}} server {{$srv.Settings.Address}} weight={{$srv.Settings.Weight}} {{if eq $srv.Settings.Availability "available"}}{{else if eq $srv.Settings.Availability "backup"}}backup{{else if eq $srv.Settings.Availability "unavailable"}}down{{end}}; {{end}} } server { {{if eq .Balancer.Settings.Protocol "http"}} listen {{.Balancer.Settings.Port}}; {{else if eq .Balancer.Settings.Protocol "https"}} listen {{.Balancer.Settings.Port}} ssl; {{end}} server_name {{.Balancer.Settings.Hostname}}; {{if eq .Balancer.Settings.Protocol "https"}} ssl on; ssl_certificate {{.Dir}}/server.crt; ssl_certificate_key {{.Dir}}/server.key; {{end}} location / { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_pass http://{{.Balancer.Id.Hex}}; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; } } `))
Reload ist die andere Funktion in der Nginx-Struktur , die NGINX dazu bringt, die Konfigurationsdateien neu zu laden. Der verwendete Mechanismus hängt davon ab, wie Loadcat konfiguriert ist. Standardmäßig wird davon ausgegangen, dass NGINX ein systemd-Dienst ist, der als nginx.service ausgeführt wird, sodass [sudo] systemd reload nginx.service
würde. Anstatt jedoch einen Shell-Befehl auszuführen, stellt es mit dem Paket github.com/coreos/go-systemd/dbus eine Verbindung zu systemd über D-Bus her.
Webbasierte GUI
Nachdem all diese Komponenten vorhanden sind, werden wir alles mit einer einfachen Bootstrap-Benutzeroberfläche abschließen.
Für diese grundlegenden Funktionalitäten reichen ein paar einfache GET- und POST-Route-Handler aus:
GET /balancers GET /balancers/new POST /balancers/new GET /balancers/{id} GET /balancers/{id}/edit POST /balancers/{id}/edit GET /balancers/{id}/servers/new POST /balancers/{id}/servers/new GET /servers/{id} GET /servers/{id}/edit POST /servers/{id}/edit
Das Durchgehen jeder einzelnen Route ist hier möglicherweise nicht das Interessanteste, da dies so ziemlich die CRUD-Seiten sind. Fühlen Sie sich absolut frei, einen Blick auf den Paket-UI-Code zu werfen, um zu sehen, wie Handler für jede dieser Routen implementiert wurden.
Jede Handler-Funktion ist eine Routine, die entweder:
- Ruft Daten aus dem Datenspeicher ab und antwortet mit gerenderten Vorlagen (unter Verwendung der abgerufenen Daten)
- Analysiert eingehende Formulardaten, nimmt notwendige Änderungen im Datenspeicher vor und verwendet das Paket feline, um die NGINX-Konfigurationsdateien neu zu generieren
Zum Beispiel:
func ServeServerNewForm(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) bal, _ := data.GetBalancer(bson.ObjectIdHex(vars["id"])) TplServerNewForm.Execute(w, struct { Balancer *data.Balancer }{ Balancer: bal, }) } func HandleServerCreate(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) bal, _ := data.GetBalancer(bson.ObjectIdHex(vars["id"])) r.ParseForm() body := struct { Label string `schema:"label"` Settings struct { Address string `schema:"address"` } `schema:"settings"` }{} schema.NewDecoder().Decode(&body, r.PostForm) srv := data.Server{} srv.BalancerId = bal.Id srv.Label = body.Label srv.Settings.Address = body.Settings.Address srv.Put() feline.Commit(bal) http.Redirect(w, r, "/servers/"+srv.Id.Hex()+"/edit", http.StatusSeeOther) }
Die ServeServerNewForm- Funktion ruft lediglich einen Balancer aus dem Datenspeicher ab und rendert eine Vorlage, in diesem Fall TplServerList , die die Liste der relevanten Server mithilfe der Servers -Funktion auf dem Balancer abruft.
Die HandleServerCreate- Funktion hingegen parst die eingehende POST-Nutzlast aus dem Hauptteil in eine Struktur und verwendet diese Daten, um eine neue Serverstruktur im Datenspeicher zu instanziieren und beizubehalten, bevor sie das Paket feline verwendet, um die NGINX-Konfigurationsdatei für den Balancer neu zu generieren.
Alle Seitenvorlagen werden in der Datei „ui/templates.go“ gespeichert und entsprechende Vorlagen-HTML-Dateien finden Sie im Verzeichnis „ui/templates“.
Ausprobieren
Die Bereitstellung von Loadcat auf einem Remote-Server oder sogar in Ihrer lokalen Umgebung ist super einfach. Wenn Sie Linux (64-Bit) ausführen, können Sie ein Archiv mit einer vorgefertigten Loadcat-Binärdatei aus dem Abschnitt „Releases“ des Repositorys abrufen. Wenn Sie sich etwas abenteuerlustig fühlen, können Sie das Repository klonen und den Code selbst kompilieren. Allerdings kann die Erfahrung in diesem Fall etwas enttäuschend sein, da das Kompilieren von Go-Programmen keine wirkliche Herausforderung darstellt. Und falls Sie Arch Linux ausführen, haben Sie Glück! Der Einfachheit halber wurde ein Paket für die Verteilung erstellt. Laden Sie es einfach herunter und installieren Sie es mit Ihrem Paketmanager. Die erforderlichen Schritte sind in der README.md-Datei des Projekts ausführlicher beschrieben.
Sobald Sie Loadcat konfiguriert und ausgeführt haben, richten Sie Ihren Webbrowser auf „http://localhost:26590“ (vorausgesetzt, er wird lokal ausgeführt und überwacht Port 26590). Erstellen Sie als Nächstes einen Balancer, erstellen Sie ein paar Server, stellen Sie sicher, dass etwas auf diesen definierten Ports lauscht, und voila, Sie sollten NGINX-Lastausgleich für eingehende Anfragen zwischen diesen laufenden Servern haben.
Was kommt als nächstes?
Dieses Tool ist alles andere als perfekt, und tatsächlich ist es ein ziemlich experimentelles Projekt. Das Tool deckt nicht einmal alle grundlegenden Funktionalitäten von NGINX ab. Wenn Sie beispielsweise Assets zwischenspeichern möchten, die von den Back-End-Knoten auf der NGINX-Ebene bereitgestellt werden, müssen Sie die NGINX-Konfigurationsdateien immer noch von Hand ändern. Und das macht die Sache spannend. Hier kann viel getan werden, und genau das kommt als Nächstes: Noch mehr Load-Balancing-Funktionen von NGINX abdecken – die grundlegenden und wahrscheinlich sogar diejenigen, die NGINX Plus zu bieten hat.
Probieren Sie Loadcat aus. Überprüfen Sie den Code, forken Sie ihn, ändern Sie ihn, spielen Sie damit. Teilen Sie uns außerdem im Kommentarbereich unten mit, ob Sie ein Tool entwickelt haben, das andere Software konfiguriert, oder eines verwendet haben, das Ihnen wirklich gefällt.