Prowid Photos-un indi üç API nüsxəsi var, amma saytın ünvanı birdir — photos.prowid.com. Brauzerdən gələn sorğu üç serverdən hansına düşəcək? Bunu yük balanslaşdırıcısı (load balancer) həll edir — «restoranın girişindəki administrator»: o, qonaqları qarşılayır, boş stolun yanına aparır, stol sınıbsa, ora daha heç kəsi oturtmur. Bu dərsdə onun nə üçün lazım olduğunu, serveri necə seçdiyini (alqoritmlər), nasazlıqlardan necə xəbər tutduğunu (health check), L4 ilə L7-nin nə ilə fərqləndiyini, Nginx-də necə qurulduğunu — və balanslaşdırıcının özünün niyə zəif halqaya çevrilə biləcəyini araşdıracağıq.
Balanslaşdırıcı nə üçün lazımdır
Balanslaşdırıcı müştərilərlə serverlər arasında dayanır və bir anda bir neçə şey verir:
- Vahid giriş nöqtəsi. Müştərilər bir ünvanı bilir və onun arxasında neçə server olduğunu bilmir.
- Yükün bölüşdürülməsi. Sorğular nüsxələrə yayılır, buna görə heç biri digərlərindən əvvəl həddindən artıq yüklənmir.
- Nasazlığa davamlılıq. Sıradan çıxmış server rotasiyadan çıxarılır və istifadəçilər bunu hiss etmir.
- Dayanmadan yeniləmələr. Server rotasiyadan çıxarılır, cari sorğularını bitirməsi gözlənilir, yenilənir və geri qaytarılır.
- Bonuslar. Balanslaşdırıcı çox vaxt eyni zamanda TLS-i (HTTPS) sonlandırır, cavabları sıxır və sorğuların tezliyini məhdudlaşdırır.
Balanslaşdırıcının rolunu öz serverinizdə Nginx və ya HAProxy, yaxud buludun idarə olunan servisi oynaya bilər. Nginx-in reverse proxy kimi əsaslarını «Nginx konteynerlər üçün reverse proxy kimi» dərsindən bilirsiniz: balanslaşdırıcı birinin yox, bir qrup serverin olduğu reverse proxy-dir.
Balanslaşdırma alqoritmləri
Round robin — «növbə ilə»: birinci sorğu birinci serverə, ikinci sorğu ikinciyə və s. Serverlər eynidirsə və sorğular oxşardırsa, sadə və ədalətlidir:
const servers = ['s1', 's2', 's3'];
let next = 0;
function pickRoundRobin() {
const server = servers[next];
next = (next + 1) % servers.length;
return server;
}
for (let i = 1; i <= 4; i++) {
console.log(`request ${i} -> ${pickRoundRobin()}`);
}
// request 1 -> s1, request 2 -> s2, request 3 -> s3, request 4 -> s1Amma sorğular bərabər deyil: yüngül GET 5 ms, foto yükləmə 3 saniyə çəkir. Növbə ilə bölüşdürəndə bir server ağır sorğulara basılıb, digəri isə boş qala bilər. Weighted round robin serverlərin müxtəlif gücünü nəzərə alır: çəkisi 2 olan server iki dəfə çox sorğu alır. Least connections sorğunu hazırda açıq bağlantısı ən az olan serverə göndərir — fayl yükləmələri və WebSocket üçün idealdır:
const connections = { s1: 3, s2: 1, s3: 2 };
function pickLeastConnections() {
let best = 's1';
for (const name of Object.keys(connections)) {
if (connections[name] < connections[best]) best = name;
}
return best;
}
console.log(pickLeastConnections()); // s2: it has the fewest open connections