Zum Inhalt springen

Nginx als Load Balancer: Traffic verteilen ohne Backend-Bingo

29. September 2026 durch
Nginx als Load Balancer: Traffic verteilen ohne Backend-Bingo
Carsten Depping

Ein einzelnes Backend ist mutig. Zwei Backends sind besser. Drei Backends mit Nginx davor fühlen sich schon fast nach erwachsenem Betrieb an.

Wir haben Nginx mal wieder als Load Balancer vor ein paar App-Server gestellt. Ziel: Traffic sauber verteilen, kaputte Backends nicht mehr anfunken und Sessions nicht bei jedem Request durch den Serverraum würfeln.

Grundsetup: Upstream definieren

Nginx kann im http-Block einen upstream definieren. Dort landen die Backends, die später vom proxy_pass genutzt werden.

# /etc/nginx/conf.d/app-loadbalancer.conf
upstream app_backend {
    server 10.10.0.11:8080;
    server 10.10.0.12:8080;
    server 10.10.0.13:8080;
}

server {
    listen 80;
    server_name app.example.local;

    location / {
        proxy_pass http://app_backend;

        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;
    }
}

Standardmäßig nutzt Nginx Round Robin. Request 1 geht an Backend 1, Request 2 an Backend 2, und so weiter. Kein Hexenwerk, aber solide.

Syntax prüfen, Reload, Kaffee:

nginx -t
systemctl reload nginx

Gewichtung: Der dickere Server bekommt mehr Arbeit

Nicht alle Backends sind gleich. Vielleicht hat 10.10.0.11 mehr CPU, mehr RAM oder einfach den besseren Deal mit dem Hypervisor-Gott. Dann bekommt er ein höheres weight.

# /etc/nginx/conf.d/app-loadbalancer.conf
upstream app_backend {
    server 10.10.0.11:8080 weight=3;
    server 10.10.0.12:8080 weight=1;
    server 10.10.0.13:8080 weight=1;
}

Damit bekommt 10.10.0.11 ungefähr dreimal so viele Requests wie die anderen. Wichtig: Das ist keine harte Echtzeit-Mathematik, sondern Verteilung über Zeit. Also bitte nicht mit watch curl und Stoppuhr eskalieren.

Backend-Ausfälle abfangen

Die freie Nginx-Version macht passive Health Checks. Bedeutet: Nginx merkt sich Fehler, wenn Requests schiefgehen. Aktive Health Checks mit regelmäßigem Pingen gibt es offiziell in Nginx Plus. Ja, schade. Nein, wir schreien nicht. Wir konfigurieren vernünftig.

# /etc/nginx/conf.d/app-loadbalancer.conf
upstream app_backend {
    server 10.10.0.11:8080 max_fails=3 fail_timeout=30s;
    server 10.10.0.12:8080 max_fails=3 fail_timeout=30s;
    server 10.10.0.13:8080 max_fails=3 fail_timeout=30s;
}

max_fails=3 heißt: Nach drei fehlgeschlagenen Versuchen gilt das Backend als kaputt. fail_timeout=30s heißt: Für 30 Sekunden wird es gemieden. Danach probiert Nginx es wieder. Wie ein Sysadmin mit einem Drucker: kurz ignorieren, dann nochmal versuchen.

Zusätzlich solltest du Timeouts setzen, sonst wartet Nginx unter Umständen zu lange auf sterbende Backends.

# /etc/nginx/conf.d/app-loadbalancer.conf
server {
    listen 80;
    server_name app.example.local;

    location / {
        proxy_pass http://app_backend;

        proxy_connect_timeout 3s;
        proxy_send_timeout 10s;
        proxy_read_timeout 10s;

        proxy_next_upstream error timeout http_500 http_502 http_503 http_504;
        proxy_next_upstream_tries 2;

        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;
    }
}

Damit darf Nginx bei Fehlern ein anderes Backend versuchen. Praktisch, wenn eine App gerade intern Feuer fängt.

Session-Stickiness: Bitte nicht mitten im Login umziehen

Wenn deine App Sessions lokal auf dem Backend hält, brauchst du Stickiness. Besser wäre natürlich ein zentraler Session-Store wie Redis. Aber wir leben nicht immer im perfekten Kubernetes-Whitepaper.

Die einfache Variante ist ip_hash.

# /etc/nginx/conf.d/app-loadbalancer.conf
upstream app_backend {
    ip_hash;

    server 10.10.0.11:8080 max_fails=3 fail_timeout=30s;
    server 10.10.0.12:8080 max_fails=3 fail_timeout=30s;
    server 10.10.0.13:8080 max_fails=3 fail_timeout=30s;
}

Nginx nimmt dabei die Client-IP und schickt denselben Client möglichst wieder zum selben Backend. Funktioniert okay, bis viele Clients hinter NAT, VPN oder Proxy sitzen. Dann sieht halb Bremen aus wie ein einzelner User. Klassiker.

Eine flexiblere Variante ist Hashing auf einen Cookie, sofern deine Anwendung einen passenden Cookie setzt.

# /etc/nginx/conf.d/app-loadbalancer.conf
upstream app_backend {
    hash $cookie_sessionid consistent;

    server 10.10.0.11:8080 max_fails=3 fail_timeout=30s;
    server 10.10.0.12:8080 max_fails=3 fail_timeout=30s;
    server 10.10.0.13:8080 max_fails=3 fail_timeout=30s;
}

consistent reduziert das große Umwürfeln, wenn ein Backend dazukommt oder verschwindet.

Kurzfazit aus dem Maschinenraum

Nginx als Load Balancer ist schnell eingerichtet und erstaunlich robust. Mit upstream, weight, max_fails, sinnvollen Timeouts und etwas Stickiness bekommst du schon viel Betriebssicherheit für wenig Konfigurationsmagie.

Nur eine Regel bleibt: Wenn Sessions lokal liegen, ist der Load Balancer nicht dein Problem. Er zeigt es dir nur sehr ehrlich.

Nginx als Load Balancer: Traffic verteilen ohne Backend-Bingo
Carsten Depping 29. September 2026
Diesen Beitrag teilen