Loading...

کارایی · 12 دقیقه مطالعه

load balancer چیست؟ ترافیک چطور پخش، چک و failover می‌شود

یک load balancer ترافیک را روی یک آدرس می‌پذیرد و آن را روی چند سرور که همگی می‌توانند به آن پاسخ دهند پخش می‌کند، و هر سروری را که health checkش را رد کند کنار می‌گذارد. این راهنما balancing در لایه 4 و لایه 7، الگوریتم‌ها، health checkها، sticky sessionها و TLS termination، پیکربندی‌های واقعی HAProxy و nginx، load balancing سراسری و DNS، و اشتباهاتی را که یک load balancer را به علت یک قطعی تبدیل می‌کنند پوشش می‌دهد.

به‌روزرسانی

load balancer چیست؟ ترافیک چطور پخش، چک و failover می‌شود

یک load balancer چه کاری می‌کند

یک load balancer بین کلاینت‌ها و گروهی از سرورها که همگی می‌توانند به یک درخواست یکسان پاسخ دهند می‌نشیند، و تصمیم می‌گیرد کدام سرور هر کدام را بگیرد. کلاینت‌ها به یک آدرس وصل می‌شوند؛ load balancer یک backend سالم را انتخاب می‌کند، درخواست را فوروارد می‌کند، و پاسخ را برمی‌گرداند.

سه کار انجام می‌دهد. بار را پخش می‌کند، پس سه سرور می‌توانند تقریباً سه برابر ترافیک یک سرور را حمل کنند. سرورهای خراب را حذف می‌کند: health checkها متوجه backendای می‌شوند که دیگر پاسخ نمی‌دهد و تا وقتی بهبود نیابد کسی را به آن نمی‌فرستند. و تغییرات را نامرئی می‌کند: می‌توانید یک سرور را بیرون بیاورید، پچش کنید، رویش deploy کنید و برش گردانید بدون آنکه بازدیدکننده‌ها خطایی ببینند.

کار دوم اغلب مهم‌تر است: دو سرور پشت یک load balancer بیشتر به این مربوط است که یکی از آن‌ها اجازهٔ از کار افتادن داشته باشد تا به ظرفیت. یک load balancer لایه 7 نوعی reverse proxy است که کارش انتخاب بین backendهای یکسان است؛ HAProxy و nginx هر دو کار را می‌کنند.

Load balancing لایه 4 در برابر لایه 7

لایه یعنی load balancer چه‌قدر از ترافیک را پیش از تصمیم‌گیری می‌خواند.

یک load balancer لایه 4 با اتصالات TCP و بسته‌های UDP کار می‌کند. آدرس و پورت مبدا و مقصد را می‌بیند، وقتی اتصال باز می‌شود یک backend انتخاب می‌کند، و بایت‌ها را در هر دو جهت کپی می‌کند. نمی‌تواند یک URL، header یا cookie ببیند، پس هر درخواست روی آن اتصال به همان سرور می‌رود. در ازایش سریع، مستقل از پروتکل (دیتابیس‌ها، MQTT، SMTP، سرورهای بازی) است و می‌تواند TLS را مستقیم عبور دهد، پس گواهی روی backendها باقی می‌ماند. mode tcp در HAProxy و بلوک stream {} در nginx همین‌جا کار می‌کنند.

یک load balancer لایه 7 به زبان HTTP صحبت می‌کند. اتصال را تمام می‌کند، هر درخواست را می‌خواند، و می‌تواند بر اساس host، path، header یا cookie مسیر دهد: /api به یک pool، / به pool دیگر، یک cookie canary به نسخهٔ جدید. می‌تواند یک درخواست شکست‌خورده را روی سرور دیگری دوباره امتحان کند و درخواست‌های یک اتصال HTTP/2 را روی چند backend پخش کند (mode http در HAProxy، http {} در nginx).

برای خواندن HTTP، یک balancer لایه 7 باید آن را رمزگشایی کند، پس TLS termination جزو لاینفک این لایه است. گواهی روی load balancer زندگی می‌کند و backendها روی شبکه‌ای خصوصی HTTP ساده می‌گیرند، یا اگر شبکه قابل‌اعتماد نباشد یک اتصال TLS دوم. هزینه‌اش این است که backend دیگر کلاینت را نمی‌بیند: load balancer را می‌بیند. balancerهای لایه 7 این را با X-Forwarded-For و X-Forwarded-Proto درست می‌کنند؛ balancerهای لایه 4 از پروتکل PROXY استفاده می‌کنند، که backend باید برای پذیرفتنش تنظیم شود.

الگوریتم‌های balancing: round robin، least connections، hashing، وزن‌ها

Round robin درخواست‌ها را به‌نوبت به هر سرور می‌دهد. تقریباً همه‌جا پیش‌فرض است و وقتی هزینهٔ درخواست‌ها تقریباً یکسان و سرورها یکسان باشند درست است.

Weighted round robin به یک سرور بزرگ‌تر سهم بزرگ‌تری می‌دهد: با وزن‌های 2، 2 و 1، سرور سوم یک‌پنجم ترافیک را می‌گیرد. وزن‌ها همچنین راه اجرای یک canary هستند: نسخهٔ جدید را با وزن کوچکی در pool بگذارید، نرخ خطایش را تماشا کنید، بعد بالا ببرید.

Least connections درخواست بعدی را به سروری می‌فرستد که کمترین اتصال فعال را دارد. وقتی هزینهٔ درخواست‌ها خیلی فرق می‌کند (reportها کنار page viewها، آپلودها کنار فراخوانی‌های API) یا اتصالات طولانی‌مدت‌اند، مثل WebSocket، از آن استفاده کنید.

IP hash (balance source در HAProxy، ip_hash در nginx) هر آدرس کلاینت را هر بار به همان سرور نگاشت می‌کند. بدون کوکی به شما affinity می‌دهد، اما توزیع از جمعیت کلاینت‌ها پیروی می‌کند: یک دفتر یا یک اپراتور موبایل پشت یک آدرس مشترک می‌تواند هزاران کاربر را روی یک backend بریزد.

Consistent hashing روی یک کلید (URI، یک شناسهٔ کاربر) همان کلید را روی همان سرور نگه می‌دارد، و وقتی سروری اضافه یا حذف شود فقط سهم کوچکی از کلیدها جابه‌جا می‌شوند. این همان چیزی است که جلوی cacheها می‌خواهید: بر اساس URI هش کنید و هر آبجکت در یک cache زندگی کند نه در همهٔ آن‌ها. nginx آن را hash $request_uri consistent; می‌نویسد، HAProxy balance uri با hash-type consistent.

هر چه را انتخاب کنید، الگوریتم کمتر از health checkهایی اهمیت دارد که راست می‌گویند.

Health check و failover

یک load balancer فقط به‌اندازهٔ تصویری که از سرورهای زنده دارد خوب است.

Active health check هر backend را با یک تایمر probe می‌کند: یک اتصال TCP باز می‌کند، یا یک URL مثل /healthz را درخواست می‌کند و 200 انتظار دارد. بعد از fall شکست پیاپی سرور down علامت می‌خورد و چیزی نمی‌گیرد؛ بعد از rise موفقیت برمی‌گردد. HAProxy این کار را در نسخهٔ متن‌باز انجام می‌دهد. nginx متن‌باز این کار را نمی‌کند: max_fails و fail_timeout چک‌های passive هستند، که درخواست‌های واقعی شکست‌خورده را می‌شمارند و سرور را مدتی استراحت می‌دهند. چک‌های active در nginx بخشی از NGINX Plus تجاری است. زمان‌بندی یک trade-off است: یک چک هر دو ثانیه با fall 3 یک سرور مرده را در حدود شش ثانیه حذف می‌کند؛ هر 30 ثانیه یعنی یک‌ونیم دقیقه خطا.

Failover چیزی است که بعدش اتفاق می‌افتد. ترافیک به سرورهای باقی‌مانده منتقل می‌شود، پس باید جا برایش داشته باشند: سه سرور که هر کدام 80٪ کار می‌کنند نمی‌توانند از دست‌دادن یکی را جذب کنند. یک سرور backup فقط وقتی ترافیک می‌گیرد که همهٔ سرورهای اصلی down باشند، که برای یک یدکی سرد یا صفحهٔ maintenance مناسب است.

بگذارید endpoint سلامت به همان سؤالی که load balancer می‌پرسد پاسخ دهد: *آیا این سرور الان باید ترافیک بگیرد؟* یعنی چک‌کردن چیزی که محلی به همان process است (شروع شده، به dependencyهای خودش می‌رسد، در حال خاموش‌شدن نیست) و برگرداندن سریع پاسخ. در طول یک deploy، اول چک را fail کنید، بگذارید درخواست‌های در حال پرواز تمام شوند (connection draining)، بعد process را متوقف کنید.

تداوم session (sticky session)

اگر یک اپلیکیشن session کاربر لاگین‌شده را در حافظهٔ یک سرور نگه دارد، درخواست بعدی باید به همان سرور برسد وگرنه کاربر logout می‌شود. تداوم session باعث می‌شود load balancer یادش بماند هر کسی کجا می‌رود.

راه‌های معمول یک کوکی تزریق‌شده هستند (load balancer کوکی‌ای اضافه می‌کند که نام سرور را می‌برد، همان‌طور که HAProxy با cookie SRV insert indirect nocache به‌همراه یک مقدار cookie روی هر سطر server انجام می‌دهد)، یک کوکی اپلیکیشن که از آن می‌آموزد (PHPSESSID، JSESSIONID)، یا hashing بر اساس IP مبدا. nginx متن‌باز فقط روش‌های hashing را دارد (ip_hash یا hash $cookie_name)؛ directive sticky متعلق به NGINX Plus است.

Stickiness هزینه دارد. بار دیگر یکسان نیست، چون چند کاربر پرمصرف روی یک سرور ثابت می‌مانند. drain‌کردن یک سرور به‌اندازهٔ طولانی‌ترین sessionش طول می‌کشد، و وقتی سروری بمیرد، کاربرانش هرحال sessionشان را از دست می‌دهند.

راه‌حل پایدار این است که سرورها را قابل‌جایگزین کنید: sessionها را در یک store مشترک مثل Redis یا دیتابیس، یا در یک کوکی امضاشده، نگه دارید و بگذارید هر سروری به هر درخواست پاسخ دهد. آن وقت یک سرور از کار افتاده login هیچ‌کس را از بین نمی‌برد.

یک پیکربندی کارکردنی HAProxy

یک پیکربندی HAProxy از بالا به پایین خوانده می‌شود: global برای process، defaults که هر بخش ارث می‌برد، یک frontend که اتصالات را می‌پذیرد و یک backend که pool را نگه می‌دارد.

مثال TLS را روی 443 تمام می‌کند (فایل .pem زنجیرهٔ گواهی و کلید خصوصی را با هم نگه می‌دارد)، HTTP ساده را ریدایرکت می‌کند، هدرهای forwarding را اضافه می‌کند، و با least connections balance می‌کند. health check یک درخواست HTTP واقعی با هدر Host است، چون خیلی از اپلیکیشن‌ها به درخواستی بدون آن 404 یا یک ریدایرکت جواب می‌دهند، و چکی که 200 انتظار دارد روی یک سرور سالم شکست می‌خورد. http-check send به HAProxy 2.2 یا جدیدتر نیاز دارد؛ نسخه‌های قدیمی‌تر درخواست را روی سطر option httpchk می‌گذارند.

default-server زمان‌بندی چک را یک‌بار تنظیم می‌کند: یک probe هر دو ثانیه، سه شکست برای down‌کردن یک سرور، دو موفقیت برای برگرداندنش. app3 ماشینی کوچک‌تر است و نیمی از سهم بقیه را می‌گیرد؛ spare فقط وقتی هر سه down باشند ترافیک می‌گیرد. برای sticky کردن sessionها، cookie SRV insert indirect nocache را به backend و cookie app1 (و همین‌طور بقیه) را به هر سطر server اضافه کنید.

پیش از هر reload، فایل را با haproxy -c -f /etc/haproxy/haproxy.cfg چک کنید.

/etc/haproxy/haproxy.cfg: TLS termination، least connections، health check HTTP

global
    log /dev/log local0
    maxconn 20000

defaults
    mode http
    log global
    option httplog
    timeout connect 5s
    timeout client  60s
    timeout server  60s

frontend fe_web
    bind :80
    bind :443 ssl crt /etc/haproxy/certs/example.com.pem alpn h2,http/1.1
    http-request redirect scheme https unless { ssl_fc }
    option forwardfor
    http-request set-header X-Forwarded-Proto https
    default_backend be_app

backend be_app
    balance leastconn
    option httpchk
    http-check send meth GET uri /healthz ver HTTP/1.1 hdr Host app.example.com
    http-check expect status 200
    default-server inter 2s fall 3 rise 2
    server app1 10.0.0.11:8080 check weight 100
    server app2 10.0.0.12:8080 check weight 100
    server app3 10.0.0.13:8080 check weight 50
    server spare 10.0.0.20:8080 check backup

Load balancing با nginx upstream

در nginx، pool یک بلوک upstream است و proxy_pass با نامش به آن اشاره می‌کند. بدون هیچ سطر الگوریتمی، nginx از weighted round robin استفاده می‌کند؛ least_conn، ip_hash، hash … consistent و random این را عوض می‌کنند.

چند جزئیات در مثال به‌راحتی از قلم می‌افتند. keepalive 32 اتصالات بی‌کار به backendها را برای استفادهٔ دوباره باز نگه می‌دارد، اما فقط به‌همراه proxy_http_version 1.1 و یک هدر Connection خالی کار می‌کند؛ بدون آن دو سطر nginx برای هر درخواست اتصال تازه باز می‌کند. max_fails=3 fail_timeout=10s یک سرور را بعد از سه درخواست شکست‌خورده در ده ثانیه، برای ده ثانیه بیرون می‌گذارد: همان health check passive nginx. backup فقط با روش‌های round robin، weighted و least_conn کار می‌کند، نه با روش‌های hashing.

proxy_next_upstream تصمیم می‌گیرد چه زمانی یک درخواست شکست‌خورده روی سرور بعدی دوباره امتحان شود. nginx به‌طور پیش‌فرض روی خطاهای اتصال و timeout دوباره امتحان می‌کند، و از نسخهٔ 1.9.13 هرگز یک POST، LOCK یا PATCH را دوباره امتحان نمی‌کند مگر non_idempotent را اضافه کنید. همین‌طور نگهش دارید: دوباره‌امتحان‌کردن یک پرداخت چون سرور اول بعد از کشیدن کارت timeout شده، از یک خطا بدتر است. proxy_next_upstream_tries 2 یک درخواست آهسته را از پیمودن کل pool متوقف می‌کند. هدرها همان‌هایی هستند که هر reverse proxy لازم دارد؛ راهنمای nginx بقیه را پوشش می‌دهد.

nginx: یک pool upstream با وزن، چک‌های passive، یک backup و keep-alive

upstream app {
    least_conn;
    server 10.0.0.11:8080 weight=2 max_fails=3 fail_timeout=10s;
    server 10.0.0.12:8080 weight=2 max_fails=3 fail_timeout=10s;
    server 10.0.0.13:8080          max_fails=3 fail_timeout=10s;
    server 10.0.0.20:8080 backup;
    keepalive 32;
}

server {
    listen 443 ssl;
    server_name example.com;
    ssl_certificate     /etc/ssl/example.com/fullchain.pem;
    ssl_certificate_key /etc/ssl/example.com/privkey.pem;

    location / {
        proxy_pass http://app;
        proxy_http_version 1.1;
        proxy_set_header Connection        "";
        proxy_set_header Host              $host;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_next_upstream error timeout http_502 http_503;
        proxy_next_upstream_tries 2;
        proxy_connect_timeout 3s;
    }
}

سراسری در برابر محلی: DNS، GeoDNS، anycast و load balancerهای ابری

همهٔ آنچه بالاتر آمد load balancing محلی است: یک سایت، یک pool، یک پروکسی در مسیر درخواست. load balancing سراسری تصمیم می‌گیرد بازدیدکننده در وهلهٔ اول به کدام سایت، منطقه یا datacentre برسد، و معمولاً پیش از آنکه هیچ پروکسی‌ای درخواست را ببیند انجام می‌شود.

DNS round robin قدیمی‌ترین شکل است: چند رکورد A منتشر کنید و resolverها آن‌ها را به ترتیب چرخشی تحویل می‌دهند. هیچ هزینه‌ای ندارد و ترافیک را تقریبی پخش می‌کند، اما DNS چیزی از سلامت نمی‌داند. آدرس یک سرور مرده تا وقتی کسی حذفش نکند همچنان تحویل داده می‌شود، و resolverها و مرورگرها پاسخ قدیمی را برای TTL رکورد و گاهی بیشتر cache می‌کنند.

GeoDNS بسته به اینکه query از کجا می‌آید پاسخ متفاوتی می‌دهد، پس بازدیدکنندگان یک کشور آدرس سایت نزدیک را می‌گیرند. همراه با health checkهای سمت DNS، این به DNS failover تبدیل می‌شود: منطقه‌ای که چکش را رد کند از پاسخ‌ها کنار گذاشته می‌شود. محدودیت‌ها همان cache‌شدن TTL است و این واقعیت که موقعیت همان موقعیت resolver است، نه بازدیدکننده، مگر اینکه resolver بخشی از آدرس کلاینت را منتقل کند (EDNS Client Subnet). راهنمای DNS TTLها و resolverها را با جزئیات پوشش می‌دهد.

Anycast همان آدرس IP را از مکان‌های زیادی روی BGP اعلام می‌کند، و مسیریابی اینترنت هر بسته را به نزدیک‌ترین مکان می‌رساند. هیچ TTLای برای صبرکردن نیست: وقتی مکانی اعلام را متوقف کند، مسیرها در عرض ثانیه‌ها تا دقیقه‌ها جابه‌جا می‌شوند. همین‌طور است که سرویس‌های بزرگ DNS و CDNها به nodeهایشان می‌رسند. لایه‌ها روی هم می‌نشینند: DNS یا anycast مکان را انتخاب می‌کند، یک پروکسی درونش سرور را انتخاب می‌کند.

Load balancerهای ابری همان ایده‌ها را به‌شکل یک سرویس مدیریت‌شده بسته‌بندی می‌کنند. AWS دارای Application Load Balancer (لایه 7) و Network Load Balancer (لایه 4) است؛ Google Cloud Load Balancing نسخه‌های سراسری و منطقه‌ای، application و network ارائه می‌دهد؛ Azure بین Azure Load Balancer (لایه 4) و Application Gateway (لایه 7) تفاوت می‌گذارد. در Kubernetes، یک Service اتصالات را روی podها پخش می‌کند و یک Ingress controller مسیریابی لایه 7 انجام می‌دهد. الگوریتم‌ها، health checkها و تله‌های این راهنما بدون تغییر برای آن‌ها هم صدق می‌کنند.

اشتباهات رایجی که قطعی می‌سازند

load balancer خودش نقطهٔ تک‌شکست می‌شود. سه application server پشت یک جعبهٔ HAProxy یعنی حالا همان جعبه چیزی است که می‌تواند شما را زمین‌گیر کند. دو جعبه اجرا کنید و یک IP شناور را با VRRP بین آن‌ها حرکت دهید (keepalived ابزار معمول است)، یا یک لایهٔ مدیریت‌شده یا سطح DNS جلویش بگذارید. بعد با خاموش‌کردن فعال فعلی تستش کنید.

health check دروغ می‌گوید، در هر دو جهت. یک /healthz که همیشه 200 برمی‌گرداند سروری را که connection pool دیتابیسش تمام شده در چرخش نگه می‌دارد، پس سهمی از درخواست‌ها شکست می‌خورند در حالی که داشبورد همه‌چیز را سبز نشان می‌دهد. برعکسش هم به‌همان‌اندازه بد است: چکی که دیتابیس مشترک را کوئری می‌کند *هر* سروری را در طول یک تته‌پته پنج‌ثانیه‌ای دیتابیس down علامت می‌زند، و یک کندی کوتاه به یک قطعی کامل تبدیل می‌شود. سرور را چک کنید، نه سیستم‌هایی که همهٔ سرورها مشترک‌اند.

timeoutهای ناهماهنگ. اگر backend اتصالات keep-alive بی‌کار را زودتر از چیزی که load balancer انتظار دارد ببندد، balancer گاهی یک درخواست را روی اتصالی می‌فرستد که backend تازه بسته، و کلاینت یک 502 نامنظم می‌گیرد. timeout keep-alive backend را طولانی‌تر از timeout بی‌کاری load balancer نگه دارید. دلایل بیشتر در راهنمای 502 Bad Gateway آمده‌اند.

آدرس کلاینت ناپدید می‌شود. بدون X-Forwarded-For (لایه 7) یا پروتکل PROXY (لایه 4)، اپلیکیشن در لاگ‌ها، rate limit و geolocation، IP load balancer را می‌بیند.

سرورهایی که یکسان نیستند. buildهای مختلف، پیکربندی مختلف، یا timestamp فایل‌های مختلف که ETag پیش‌فرض را عوض می‌کند، پس revalidation مرورگر هر وقت سرور دیگر پاسخ دهد یک 200 کامل برمی‌گرداند نه یک 304. یک artefact را همه‌جا deploy کنید.

تست کردن ساده است. در طول تست نام backend را در یک هدر پاسخ expose کنید و روی درخواست‌ها حلقه بزنید؛ توزیع را تماشا کنید، بعد یک backend را متوقف کنید و حرکت درخواست‌ها را ببینید.

توزیع را ببینید، وضعیت سرور را بخوانید، یک سرور را drain کنید
# which backend answered? (expose the server name in a debug header first)
for i in $(seq 1 10); do
  curl -s -o /dev/null -D - https://example.com/ | grep -i '^x-served-by'
done

# HAProxy: live state of every server through the runtime socket
# (needs "stats socket /run/haproxy/admin.sock mode 660 level admin" in global)
echo "show servers state be_app" | socat stdio /run/haproxy/admin.sock

# take one server out gracefully before a deploy, then put it back
echo "set server be_app/app1 state drain" | socat stdio /run/haproxy/admin.sock
echo "set server be_app/app1 state ready" | socat stdio /run/haproxy/admin.sock

جایی که یک CDN می‌نشیند، و کاری که CDN.com.tr می‌کند

یک CDN همان load balancing سراسری است که لازم نیست خودتان بسازید. بازدیدکنندگان به یک سرور edge نزدیک‌شان مسیر داده می‌شوند، edgeها هر چه بتوانند از cache پاسخ می‌دهند، و فقط missها به origin شما سفر می‌کنند. CDN.com.tr سرورهای edge را در ترکیه و خارج از آن اجرا می‌کند و بازدیدکنندگان را رویشان پخش می‌کند، پس پخش‌کردن بازدیدکنندگان روی مکان‌ها از قبل، پیش از رسیدن یک درخواست به هر چیزی که شما اداره می‌کنید، انجام شده است.

چیزی که همچنان خودتان هستید origin است. برای یک سایت Pull CDN، edge از Source Address که در پنل تنظیم می‌کنید، یک IP یا یک دامنه، fetch می‌کند. اگر چند origin server اجرا می‌کنید، load balancerای که بینشان انتخاب می‌کند پشت همان آدرس می‌نشیند، و هر چیزی در این راهنما برایش صدق می‌کند. آن را قفل کنید تا فقط از edge اتصال بپذیرد: راهنمایی خود پنل این است که آدرس origin را از DNS عمومی دور نگه دارید تا تنها مسیر از edge بگذرد.

edge همچنین شکست‌های origin را نرم می‌کند. محتوایی که از قبل در cache edge است در طول TTLاش حتی وقتی origin خاموش است سرویس‌دهی را ادامه می‌دهد، و گزارش کیفیت ترافیک یک نسخهٔ cache‌شده را که در حالی که origin آهسته یا در حال شکست بود سرویس‌دهی شده STALE علامت می‌زند. همان گزارش سلامت origin را هم نشان می‌دهد: درخواست‌ها به origin، سهم retry، خطاهای اتصال (502/504) و میانگین زمان رسیدن اولین بایت origin. آبجکت‌های cache‌نشده و منقضی‌شده همچنان به یک origin کارکردنی نیاز دارند، برای همین origin برای صفحات داینامیک همچنان به redundancy خودش نیاز دارد.

اگر ترجیح می‌دهید اصلاً این لایه را اجرا نکنید، container appهای CDN.com.tr به‌ازای هر اپ یک تعداد replica و یک health check (مسیر HTTP، TCP یا هیچ‌کدام) می‌گیرند. ترافیک از edge وارد می‌شود؛ با چند replica، اگر یک container در حال restart یا ناسالم باشد بقیه همچنان سرویس می‌دهند، و rolloutها health-gated هستند، پس deploy‌کردن نسخهٔ جدید پنجره‌ای باز نمی‌کند که اپ در آن غیرقابل‌دسترس باشد. sessionها به Redis مدیریت‌شده می‌روند، پس کاربر هر replicaای که درخواست بعدی را سرویس دهد همچنان لاگین می‌ماند: همان طراحی بدون حالت که بالاتر توصیه شد، بدون کوکی sticky.

پرسش‌های پرتکرار دربارهٔ load balancer

برای load balancing، HAProxy یا nginx؟

هر دو سریع و قابل‌اعتمادند. HAProxy health checkهای active، stickiness با کوکی، یک API زمان‌اجرا برای drain‌کردن سرورها و آمار بسیار دقیق در نسخهٔ رایگان دارد، که آن را به load balancer خالصِ کامل‌تر تبدیل می‌کند. nginx وقتی همان جعبه فایل هم سرویس می‌دهد، cache می‌کند یا مسیریابی چند سایت را اجرا می‌کند انتخاب بهتری است، اما نسخهٔ رایگانش فقط health check passive دارد.

تفاوت load balancing لایه 4 و لایه 7 چیست؟

لایه 4 به‌ازای هر اتصال TCP یا جریان UDP یک سرور انتخاب می‌کند و هرگز محتوا را نمی‌خواند، پس برای هر پروتکلی کار می‌کند و می‌تواند TLS را دست‌نخورده عبور دهد. لایه 7 هر درخواست HTTP را می‌خواند، پس می‌تواند بر اساس URL، header یا cookie مسیر دهد، روی سرور دیگری دوباره امتحان کند و هدرهای forwarding اضافه کند، به قیمت تمام‌کردن TLS.

کدام الگوریتم load balancing را استفاده کنم؟

برای سرورهای یکسان و درخواست‌های مشابه با round robin شروع کنید. وقتی طول درخواست‌ها خیلی فرق می‌کند یا اتصالات باز می‌مانند، مثل WebSocket، به least connections سوییچ کنید. وقتی یک کلید یکسان باید به یک سرور یکسان برسد، مثل URLها جلوی یک لایهٔ cache، از consistent hashing استفاده کنید.

آیا DNS round robin یک load balancer واقعی است؟

ترافیک را پخش می‌کند، اما سلامت را چک نمی‌کند و پاسخ‌هایش برای TTL رکورد cache می‌شوند، پس کلاینت‌ها همچنان یک آدرس مرده را امتحان می‌کنند. برای توزیع تقریبی بین سایت‌هایی که هر کدام load balancer خودشان را دارند خوب است، و به‌تنهایی برای failover ضعیف است.

اگر از یک CDN استفاده می‌کنم آیا به load balancer نیاز دارم؟

CDN بازدیدکنندگان را روی سرورهای edge خودش پخش می‌کند و بیشتر ترافیک را از cache می‌جذب می‌کند. اگر origin شما یک سرور است، برای ظرفیت به یک balancer نیاز ندارید، گرچه origin همچنان برای هر چیز cache‌نشده نقطهٔ تک‌شکست است. وقتی دو یا چند origin server اجرا کنید، یک load balancer پشت همان آدرسی که CDN از آن fetch می‌کند بگذارید.