Network load balancing traffic distribution

ตั้งค่า Nginx Load Balancing เพื่อกระจาย Traffic

มิถุนายน 2026 · อ่าน 7 นาที

Load Balancing คือเทคนิคที่ช่วยกระจาย Traffic จากผู้ใช้ออกไปยังหลาย Server พร้อมกัน ทำให้ระบบรองรับผู้ใช้ได้มากขึ้น ลด Downtime และป้องกันไม่ให้ Server ใด Server หนึ่งรับภาระหนักเกินไป ในบทความนี้จะสอนการตั้งค่า Nginx ให้ทำหน้าที่เป็น Load Balancer แบบ Reverse Proxy กระจาย Request ไปยัง Backend Server หลายตัวด้วยวิธีต่าง ๆ

สถาปัตยกรรมที่ใช้ในบทความนี้

ในตัวอย่างนี้เราจะมี Server ทั้งหมด 3 เครื่อง ได้แก่

ในสภาพแวดล้อมจริง Backend Server ทั้งสองควรรัน Application เหมือนกันทุกประการ และเชื่อมต่อ Database ร่วมกัน (Shared DB หรือ DB Cluster) เพื่อให้ผู้ใช้ได้รับข้อมูลที่สอดคล้องกันไม่ว่าจะ Route ไปหา Backend ใด

ติดตั้ง Nginx บนเครื่อง Load Balancer

เชื่อมต่อเข้า Load Balancer แล้วติดตั้ง Nginx ด้วยคำสั่งต่อไปนี้

# อัปเดต Package List
sudo apt update && sudo apt upgrade -y

# ติดตั้ง Nginx
sudo apt install nginx -y

# ตรวจสอบ Version
nginx -v

# เปิดใช้งาน Nginx ให้ Start อัตโนมัติ
sudo systemctl enable nginx
sudo systemctl start nginx

ทำความเข้าใจ Load Balancing Algorithm ทั้ง 3 แบบ

1. Round Robin (ค่าเริ่มต้น)

Nginx จะส่ง Request ไปยัง Backend แต่ละตัวแบบวนเวียน ตัวที่ 1 → ตัวที่ 2 → ตัวที่ 1 → ตัวที่ 2 เหมาะกับ Backend ที่มีสเปกใกล้เคียงกันและ Request แต่ละอันใช้เวลาประมวลผลพอ ๆ กัน

2. Least Connections

Nginx จะส่ง Request ใหม่ไปยัง Backend ที่มี Active Connection น้อยที่สุดในขณะนั้น เหมาะมากสำหรับงานที่แต่ละ Request ใช้เวลาไม่เท่ากัน เช่น File Upload หรือ API ที่มี Response Time แตกต่างกันมาก

3. IP Hash

Nginx คำนวณ Hash จาก IP Address ของ Client แล้วส่งไปยัง Backend ตัวเดิมเสมอ ทำให้ผู้ใช้คนเดิมถูก Route ไปหา Server เดิมตลอด เหมาะกับ Application ที่เก็บ Session ไว้บน Server (Sticky Session)

ตั้งค่า Round Robin Load Balancing

สร้างไฟล์ Config ใหม่สำหรับ Load Balancer

sudo nano /etc/nginx/conf.d/loadbalancer.conf

ใส่ Config ต่อไปนี้

upstream backend_pool {
    server 10.0.0.11:80;
    server 10.0.0.12:80;
}

server {
    listen 80;
    server_name yourdomain.com;

    location / {
        proxy_pass http://backend_pool;
        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;
    }
}

จากนั้นตรวจสอบ Config และ Reload Nginx

sudo nginx -t
sudo systemctl reload nginx

ตั้งค่า Least Connections

เพียงเพิ่ม least_conn; เข้าไปใน Block upstream

upstream backend_pool {
    least_conn;
    server 10.0.0.11:80;
    server 10.0.0.12:80;
}

ตั้งค่า IP Hash

เพิ่ม ip_hash; แทน

upstream backend_pool {
    ip_hash;
    server 10.0.0.11:80;
    server 10.0.0.12:80;
}
IP Hash เหมาะกับ Application ที่ยังไม่ได้ย้าย Session ไปเก็บใน Redis หรือ Database กลาง แต่ถ้าทำได้ ควรใช้ Least Connections หรือ Round Robin แล้วย้าย Session ออกจาก Local Server จะยืดหยุ่นกว่า

กำหนด Weight ให้แต่ละ Backend

ถ้า Backend แต่ละตัวมีสเปกไม่เท่ากัน สามารถกำหนดค่า Weight เพื่อให้ Backend ที่แรงกว่ารับ Traffic มากกว่าได้

upstream backend_pool {
    server 10.0.0.11:80 weight=3;   # รับ 3 ส่วน
    server 10.0.0.12:80 weight=1;   # รับ 1 ส่วน
}

ในตัวอย่างนี้ Backend 1 จะรับ Request 3 ใน 4 ครั้ง ส่วน Backend 2 รับ 1 ใน 4 ครั้ง

ตั้งค่า Health Check และ Failover

Nginx สามารถกำหนดให้ระบบ Mark Backend ที่ล้มเหลวว่า "ออฟไลน์" ชั่วคราวได้ด้วย Directive max_fails และ fail_timeout

upstream backend_pool {
    least_conn;
    server 10.0.0.11:80 max_fails=3 fail_timeout=30s;
    server 10.0.0.12:80 max_fails=3 fail_timeout=30s;
}

นอกจากนี้ยังสามารถเพิ่ม Backup Server สำหรับใช้เมื่อ Backend หลักทั้งหมดล้มเหลว

upstream backend_pool {
    server 10.0.0.11:80;
    server 10.0.0.12:80;
    server 10.0.0.99:80 backup;   # ใช้เมื่อตัวหลักทั้งสองล้มเหลว
}

เพิ่ม Timeout และ Buffer Settings

ปรับค่า Proxy Timeout ให้เหมาะสมกับ Application โดยแก้ไขในส่วน location /

location / {
    proxy_pass http://backend_pool;
    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;

    proxy_connect_timeout 10s;
    proxy_send_timeout    60s;
    proxy_read_timeout    60s;

    proxy_buffering       on;
    proxy_buffer_size     16k;
    proxy_buffers         4 16k;
}

เปิดใช้ HTTPS กับ Load Balancer

ติดตั้ง Certbot เพื่อขอ SSL Certificate จาก Let's Encrypt

sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d yourdomain.com

Certbot จะแก้ไข Config ให้อัตโนมัติ เพิ่ม Redirect HTTP → HTTPS และ SSL Certificate ให้เรียบร้อย

Backend Server ทั้งสองไม่จำเป็นต้องมี SSL Certificate เพราะการเข้ารหัสจะเกิดขึ้นระหว่าง Client กับ Load Balancer เท่านั้น (SSL Termination) การสื่อสารระหว่าง Load Balancer กับ Backend เป็น Internal Network จึงใช้ HTTP ธรรมดาได้ แต่ถ้าต้องการ End-to-End Encryption ต้องเปิด SSL บน Backend ด้วยและเปลี่ยน proxy_pass เป็น https://

ทดสอบ Load Balancing

ให้ Backend แต่ละตัว Return ค่าที่แตกต่างกันเพื่อยืนยันว่า Traffic ถูกกระจายจริง

# บน Backend 1 (10.0.0.11)
echo "Response from Backend 1" | sudo tee /var/www/html/index.html

# บน Backend 2 (10.0.0.12)
echo "Response from Backend 2" | sudo tee /var/www/html/index.html

จากนั้นทดสอบโดยใช้ curl บนเครื่อง Client

for i in {1..6}; do
    curl -s http://yourdomain.com/
done

ผลลัพธ์ที่ควรได้ (Round Robin)

Response from Backend 1
Response from Backend 2
Response from Backend 1
Response from Backend 2
Response from Backend 1
Response from Backend 2
ถ้าผลลัพธ์ไม่สลับกัน ให้ตรวจสอบว่า Nginx Cache ถูกเปิดอยู่หรือไม่ และ Browser Cache ก็อาจทำให้ผลทดสอบผิดพลาดได้ ควรใช้ curl แทน Browser เสมอ

ตรวจสอบ Log และ Monitor

ดู Access Log เพื่อตรวจสอบว่า Request ถูกส่งไปยัง Backend ไหน

sudo tail -f /var/log/nginx/access.log

เพิ่ม Log Format พิเศษเพื่อแสดง Upstream ที่ถูกเลือก

# เพิ่มใน /etc/nginx/nginx.conf ใน block http {}
log_format upstream_log '$remote_addr - $upstream_addr [$time_local] '
                        '"$request" $status $body_bytes_sent '
                        '"$http_referer" "$http_user_agent"';

แล้วระบุ Format ใน access_log

access_log /var/log/nginx/upstream.log upstream_log;

สรุป

การตั้งค่า Nginx Load Balancing ช่วยให้ระบบของคุณรองรับผู้ใช้ได้มากขึ้นและทนทานต่อความล้มเหลวของ Backend Server แต่ละตัว ขอสรุป Checklist ที่ควรทำก่อน Go Live

  1. ติดตั้ง Nginx บน Load Balancer และสร้างไฟล์ Config ใน /etc/nginx/conf.d/
  2. เลือก Algorithm ให้เหมาะกับงาน — Round Robin สำหรับ Request ที่ใช้เวลาเท่ากัน, Least Connections สำหรับงานที่ Response Time ต่างกัน, IP Hash สำหรับ Sticky Session
  3. ตั้งค่า max_fails และ fail_timeout เพื่อให้ระบบ Failover ได้อัตโนมัติ
  4. เปิด HTTPS ด้วย Certbot และใช้ SSL Termination ที่ Load Balancer
  5. ทดสอบด้วย curl และตรวจสอบ Log ว่า Traffic กระจายไปยัง Backend ทุกตัวจริง
  6. ย้าย Session ไปเก็บใน Redis หรือ Database กลาง เพื่อลดการพึ่งพา IP Hash

เมื่อระบบโตขึ้น สามารถเพิ่ม Backend Server เข้าไปใน upstream Block ได้ทันทีโดยไม่ต้องหยุด Service โดย Reload Nginx เพียงครั้งเดียว ก็พร้อมรับ Traffic บน Backend ตัวใหม่ได้เลย

ตรวจสอบว่า Load Balancing ทำงานถูกต้อง

# ตรวจสอบ Nginx config syntax
nginx -t

# ทดสอบว่า traffic กระจายไปทั้งสอง backend
for i in {1..6}; do curl -s http://yourdomain.com/; done
# ควรสลับระหว่าง Backend 1 และ Backend 2

# ดู upstream log แบบ real-time
tail -f /var/log/nginx/upstream.log

# ตรวจสอบ backend ที่ active
curl http://localhost/nginx_status   # ถ้าเปิด stub_status ไว้
Tip: เพิ่ม add_header X-Served-By $upstream_addr; ใน location block ระหว่าง debug เพื่อดูใน response header ว่า request ถูกส่งไป backend ไหน — อย่าลืมลบออกก่อน production

แก้ปัญหาที่พบบ่อย

Error: "502 Bad Gateway" จาก load balancer

Backend server ไม่ตอบสนอง หรือ Nginx ไม่สามารถเชื่อมต่อ backend ได้ ตรวจสอบ:

# ตรวจสอบว่า backend service รันอยู่
curl -s http://10.0.0.11/   # ทดสอบตรง ๆ ที่ backend

# ดู error log ของ Nginx
tail -50 /var/log/nginx/error.log

# ตรวจสอบ firewall ของ backend
# Backend ต้องเปิด port 80 จาก IP ของ load balancer

Error: Traffic ไปแต่ backend เดียว ไม่กระจาย

มักเกิดจาก browser cache หรือ Nginx proxy cache ที่ทำให้ request เดิมไปหา backend เดิม:

# ทดสอบด้วย curl แทน browser เสมอ
for i in {1..4}; do curl -s -o /dev/null -w "%{http_code} %{time_total}\n" http://yourdomain.com/; done

# ตรวจสอบว่าไม่มี proxy_cache เปิดอยู่
grep -r "proxy_cache" /etc/nginx/conf.d/

Error: Session หายเมื่อ user ถูก route ไป backend อื่น

Application เก็บ session ใน local file/memory ทำให้ backend ต่างตัวไม่รู้จัก session นั้น:

# วิธีแก้ระยะสั้น: ใช้ ip_hash (sticky session)
upstream backend_pool {
    ip_hash;
    server 10.0.0.11:80;
    server 10.0.0.12:80;
}

# วิธีแก้ระยะยาว: ย้าย session ไป Redis กลาง
# WordPress: ติดตั้ง WP Redis Object Cache plugin
# Laravel: SESSION_DRIVER=redis ใน .env

Error: Backend หนึ่งตัวล้มเหลว แต่ load balancer ยังส่ง traffic ไปอยู่

ต้องตั้ง max_fails และ fail_timeout ให้ถูกต้องใน upstream config:

upstream backend_pool {
    server 10.0.0.11:80 max_fails=3 fail_timeout=30s;
    server 10.0.0.12:80 max_fails=3 fail_timeout=30s;
}
# หลัง reload Nginx จะ mark backend ว่า down หลัง fail 3 ครั้ง
# และลองใหม่หลัง 30 วินาที

Error: "upstream timed out (110: Connection timed out)"

Backend ช้าเกินกว่า timeout ที่ตั้งไว้ ให้เพิ่ม read timeout หรือ debug ว่า backend ช้าเพราะอะไร:

location / {
    proxy_pass http://backend_pool;
    proxy_read_timeout 120s;    # เพิ่มจาก default 60s
    proxy_connect_timeout 10s;
}

คำถามที่พบบ่อย

ต้องการ VPS กี่เครื่องสำหรับ load balancing?

ขั้นต่ำ 2 เครื่อง: 1 load balancer + 1 backend แต่ที่ทำให้ high availability จริงคือ 3 เครื่อง: 1 load balancer + 2 backend ถ้า backend ตัวหนึ่งล้มเหลว อีกตัวรับงานต่อได้ทันที สำหรับ production จริงควรมี load balancer 2 ตัวด้วย (HA Proxy pair)

load balancer ทำ SSL termination หมายความว่าอะไร?

SSL termination แปลว่า load balancer รับการ decrypt SSL จาก client แล้วส่ง HTTP ธรรมดาไป backend การ์ตั้ง SSL certificate ทำแค่ที่ load balancer ตัวเดียว backend ไม่ต้องมี certificate เลย ทำให้จัดการ certificate ง่ายขึ้นมาก และ backend ไม่เปลือง CPU กับ SSL handshake

เพิ่ม backend server ตัวใหม่ต้อง restart Nginx ไหม?

แค่ reload เท่านั้น เพิ่ม IP ใหม่ใน upstream block แล้ว nginx -t && systemctl reload nginx — reload ไม่ kill connection ที่กำลังทำงานอยู่ ต่างจาก restart ที่จะ drop active connections ทั้งหมด