Reverse Proxy Olarak HAProxy mi Nginx mi: Nasıl Seçiyorum
Nginx ve HAProxy sürekli kıyaslanıyor, ve dürüst cevap aralarında çok büyük bir overlap olduğu, ikisi de TLS terminate edebiliyor, ikisi de birden fazla backend'e load balance edebiliyor, ikisi de hostname'e ya da path'e göre route edebiliyor. Çok büyük sayıda setup için ikisi de gayet iyi çalışırdı. Ama farklı birincil işler düşünülerek build edilmişler, ve bu fark, bir setup "proxy'nin arkasında bir app server" aşamasını geçtiğinde detaylarda kendini gösteriyor.
Nginx: tek bir app server için varsayılan
Tek bir application server varsa, belki bir iki static asset directory'siyle, ve proxy'nin işi büyük ölçüde TLS termination ile request'leri doğru yere route etmekse, Nginx daha basit seçim ve bunu iyi yapıyor:
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
location /static/ {
root /var/www/example.com;
}
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
Bu config aynı anda üç iş yapıyor, static dosyaları direkt serve etmek, TLS terminate etmek, ve diğer her şeyi app'e proxy'lemek, ve tek bir backend için bu tam doğru miktarda complexity. Nginx'in config syntax'ı ayrıca çoğu developer'ın en azından bir kere gördüğü bir şey, ki bu config'e başka insanların da dokunması gerektiğinde önemli oluyor.
HAProxy: birden fazla backend olduğunda varsayılan
Proxy'nin arkasında uygulamanın birden fazla instance'ı olduğu an, sorular değişiyor: şu anda hangi backend'ler healthy, load aralarında nasıl dağıtılmalı, ve bir backend ölürse mid-flight bir request'e ne oluyor. Bu HAProxy'nin core işi, ve bu, ne kadar direkt ifade edildiğinde görülüyor:
frontend web
bind *:443 ssl crt /etc/haproxy/certs/example.com.pem
default_backend app_servers
backend app_servers
balance roundrobin
option httpchk GET /healthz
server app1 10.0.0.11:3000 check
server app2 10.0.0.12:3000 check
server app3 10.0.0.13:3000 check
option httpchk GET /healthz, HAProxy'nin her backend'in health endpoint'ini aktif olarak poll ettiği anlamına geliyor, ve health check'leri fail etmeye başlayan bir backend, manuel bir müdahaleye gerek kalmadan otomatik olarak rotation'dan çıkıyor. HAProxy'nin stats page'i (stats direktifi, genelde kendi port'unda), hangi backend'lerin up olduğunun, her birinin kaç connection'ı handle ettiğinin, ve backend başına response time'ların live bir görünümünü veriyor, ki takip edilecek birden fazla server olduğunda bu gerçekten kullanışlı hale geliyor.
İkisini birlikte kullanmak
Bunlar birbirini dışlamıyor, ve tek bir server'ın ötesindeki her şey için yaygın bir setup, edge'de TLS termination ve birden fazla app server arasında load balancing yapan HAProxy, ve her app server'ın static dosyaları serve edip application process'e proxy'lemek için Nginx çalıştırması. HAProxy'nin static dosyalar hakkında hiçbir şey bilmesine gerek yok, ve Nginx'in diğer server'lar hakkında hiçbir şey bilmesine gerek yok, her parça en iyi yaptığı işi yapıyor.
Asıl karar
Tek bir backend varsa ve asıl iş TLS termination ile basic routing'se, Nginx daha basit, onu maintain edecek çoğu kişi için daha aşina, ve tamamen yeterli, tek bir backend'in önüne HAProxy koymak, çok fazla capability eklemeden bir layer ekliyor. Birden fazla backend instance'ı varsa ve health-aware load balancing önemliyse, sadece redundancy için iki app server bile olsa, HAProxy'nin load balancing ve health check modeli tam olarak bunun için build edilmiş, ve bunu Nginx'te replicate etmeye çalışmak, aynı sonuç için HAProxy'nin gerektirdiğinden daha fazla third-party module ya da daha karmaşık configuration'a uzanmak demek.
Soru hangi tool'un daha iyi olduğu değil. Soru, "bu request hangi backend'e gitmeli, ve bu backend zaten healthy mi" sorusunun, setup'ınızın cevaplamasını gerektirdiği bir soru olup olmadığı, bu noktaya gelindiğinde, HAProxy yerini kazanıyor.