Nginx

Reverse proxy va load balancing

Zamonaviy veb-ilovalar (Node.js, Python, Java) ko'pincha o'z ichki serveriga ega bo'lib, ma'lum portda (masalan, 3000) ishlaydi. Lekin bu ilovalarni to'g'ridan-to'g'ri internetga ochish yaxshi emas. Buning o'rniga oldiga Nginx qo'yiladi โ€” bu reverse proxy deb ataladi. Ushbu darsda reverse proxy va load balancing'ni batafsil o'rganamiz.

Reverse proxy nima?

Reverse proxy (teskari proksi) โ€” bu klient (brauzer) bilan orqa fondagi ilova o'rtasida turuvchi vositachi. Brauzer faqat Nginx bilan gaplashadi, Nginx esa so'rovni orqadagi ilovaga uzatib, javobni qaytaradi.

Jarayon quyidagicha kechadi:

  1. Brauzer https://mysite.com ga so'rov yuboradi;
  2. Nginx bu so'rovni 80/443 portida qabul qiladi;
  3. Nginx so'rovni ichki ilovaga uzatadi (masalan, http://localhost:3000);
  4. Node.js ilovasi javob tayyorlaydi;
  5. Nginx bu javobni brauzerga qaytaradi.

Reverse proxy'ning afzalliklari:

proxy_pass โ€” so'rovni uzatish

So'rovni orqadagi ilovaga uzatish uchun proxy_pass direktivasi ishlatiladi. Faraz qilaylik, Node.js ilovasi localhost:3000 da ishlayapti:

server {
    listen 80;
    server_name mysite.com;

    location / {
        proxy_pass http://localhost:3000;
    }
}

Endi mysite.com ga kelgan har bir so'rov localhost:3000 da ishlayotgan Node.js ilovasiga uzatiladi. Brauzer buni sezmaydi โ€” u faqat Nginx bilan ishlaydi.

localhost:3000 โ€” bu serverning o'zidagi 3000-port. Node.js ilovasini shu portda ishga tushirasiz (masalan, Express'da app.listen(3000)), Nginx esa unga so'rovlarni uzatadi.

proxy_set_header โ€” sarlavhalarni to'g'ri uzatish

Nginx so'rovni uzatganda, orqadagi ilova haqiqiy klient haqidagi ma'lumotni yo'qotishi mumkin. Chunki ilova nazarida so'rov Nginx'dan (localhost'dan) kelmoqda. Buni tuzatish uchun maxsus sarlavhalarni qo'lda o'rnatamiz:

location / {
    proxy_pass http://localhost:3000;

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

Har bir sarlavhaning vazifasi:

X-Real-IP ni uzatmasangiz, ilovangiz barcha so'rovlarni bir xil IP (localhost yoki Nginx IP'si) dan kelayotgandek ko'radi. Bu foydalanuvchi statistikasi, ban qilish yoki geolokatsiya kabi funksiyalarni buzadi. Shuning uchun reverse proxy'da bu sarlavhalar deyarli har doim o'rnatiladi.

WebSocket'ni qo'llab-quvvatlash

Agar ilovangiz WebSocket (real vaqtli ulanish, masalan chat) ishlatsa, qo'shimcha sarlavhalar kerak bo'ladi:

location / {
    proxy_pass http://localhost:3000;

    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
}

Bu sarlavhalar oddiy HTTP ulanishini WebSocket ulanishiga "ko'tarish" (upgrade) imkonini beradi.

Load balancing va upstream bloki

Agar saytingizga juda ko'p trafik kelsa, bitta ilova serveri yetmasligi mumkin. Yechim โ€” ilovaning bir nechta nusxasini (masalan, 3000, 3001, 3002 portlarida) ishga tushirib, so'rovlarni ular orasida taqsimlash. Buning uchun upstream bloki ishlatiladi:

# orqa fondagi serverlar guruhini e'lon qilamiz
upstream backend {
    server localhost:3000;
    server localhost:3001;
    server localhost:3002;
}

server {
    listen 80;
    server_name mysite.com;

    location / {
        proxy_pass http://backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Bu yerda upstream backend { ... } โ€” uchta server nusxasidan iborat guruh yaratadi. proxy_pass http://backend; esa so'rovni shu guruhga (aniq bir serverga emas) uzatadi. Nginx so'rovlarni serverlar orasida avtomatik taqsimlaydi.

Load balancing usullari

Nginx so'rovlarni serverlar orasida qanday taqsimlashini bir necha usulda sozlash mumkin:

round-robin (standart)

Standart usul. So'rovlar serverlarga navbat bilan beriladi: birinchi so'rov 1-serverga, ikkinchisi 2-serverga, uchinchisi 3-serverga, keyin yana 1-serverga va h.k. Hech qanday qo'shimcha sozlash kerak emas:

upstream backend {
    server localhost:3000;
    server localhost:3001;
    server localhost:3002;
}

least_conn (eng kam ulanish)

So'rov ayni damda eng kam faol ulanishga ega bo'lgan serverga yuboriladi. Bu so'rovlar turli vaqt talab qilganda foydali โ€” band serverlarga kamroq yuk tushadi:

upstream backend {
    least_conn;
    server localhost:3000;
    server localhost:3001;
}

ip_hash (IP bo'yicha)

Bir xil IP'dan kelgan so'rovlar doim bir xil serverga yuboriladi. Bu sessiya (login holati) serverda saqlanadigan holatlarda foydali:

upstream backend {
    ip_hash;
    server localhost:3000;
    server localhost:3001;
}

Server vaznlari va zaxira

Serverlar quvvati har xil bo'lsa, ularga vazn (weight) berish mumkin โ€” kuchliroq serverga ko'proq so'rov tushadi:

upstream backend {
    server localhost:3000 weight=3;   # 3 barobar ko'p so'rov oladi
    server localhost:3001 weight=1;
    server localhost:3002 backup;     # faqat boshqalar ishlamay qolsa ishlaydi
}
Bir domende bir necha ilovani birlashtirish uchun turli location larda turli proxy_pass ishlatishingiz mumkin: location /api/ ni Node.js'ga, location / ni esa statik saytga yo'naltirish.

To'liq namuna: statik + API

Amalda ko'p uchraydigan holat โ€” statik fayllarni Nginx beradi, /api/ so'rovlarini esa Node.js ilovasiga uzatadi:

upstream api_backend {
    least_conn;
    server localhost:3000;
    server localhost:3001;
}

server {
    listen 80;
    server_name mysite.com;
    root /var/www/mysite;
    index index.html;

    # statik fayllar Nginx tomonidan beriladi
    location / {
        try_files $uri $uri/ /index.html;
    }

    # /api/ so'rovlari Node.js ilovasiga uzatiladi
    location /api/ {
        proxy_pass http://api_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;
    }
}

Xulosa