Nginx Reverse Proxy และ Load Balancer — คู่มือ Production ฉบับสมบูรณ์ 2026
Nginx เป็น web server ที่ทรงพลังที่สุดในโลก ณ ปี 2026 มีเว็บไซต์กว่า 34% ทั่วโลกใช้ Nginx เป็น web server หลัก แต่ความสามารถที่แท้จริงของ Nginx ไม่ได้อยู่แค่การ serve static files — มันคือ Reverse Proxy และ Load Balancer ระดับ enterprise ที่ handle ได้หลายล้าน concurrent connections ด้วย resource น้อยนิด
ผมใช้ Nginx มาตั้งแต่ version 0.6 ในปี 2008 ดูแล Nginx ที่ handle traffic กว่า 100,000 requests per second ทุกวัน ผ่านมาทั้ง Apache → Nginx migration, HTTP/2 adoption, และล่าสุด HTTP/3 QUIC บทความนี้จะแชร์ทุกอย่างที่ผมเรียนรู้มาตลอด 18 ปี
สิ่งที่จะได้เรียนรู้:
- Nginx Architecture — ทำไมถึงเร็วกว่า Apache
- Reverse Proxy Setup แบบ step-by-step
- Load Balancing Algorithms ทุกแบบ
- SSL/TLS Termination + HTTP/2 + HTTP/3
- Health Checks และ Failover
- Rate Limiting และ Security
- Caching Strategy ที่ลด backend load 90%
- WebSocket Proxy
- Production Config ที่ใช้จริง
Nginx Architecture — ทำไมถึงเร็วกว่า Apache
Apache ใช้ process/thread-per-connection model — ทุก connection ใช้ 1 thread ถ้ามี 10,000 connections ก็ต้องมี 10,000 threads ซึ่งกิน RAM มหาศาลและ context switching ช้า
Nginx ใช้ event-driven, asynchronous, non-blocking architecture — 1 worker process สามารถ handle หลายพัน connections พร้อมกันด้วย epoll (Linux) หรือ kqueue (BSD) ทำให้ใช้ RAM น้อยมากและ handle concurrent connections ได้มากกว่า Apache 10-100 เท่า
# ดู Nginx architecture
# Master process → จัดการ config, workers
# Worker processes → handle connections (1 worker = หลายพัน connections)
# Cache manager → จัดการ cache
# Cache loader → load cache เมื่อ start
ps aux | grep nginx
# root 12345 master process /usr/sbin/nginx
# www-data 12346 worker process
# www-data 12347 worker process
# www-data 12348 worker process
# www-data 12349 worker process
อ่านต่อ: metallb load balancer network segmentation
ติดตั้ง Nginx — เลือก Version ที่ถูกต้อง
Nginx Open Source vs Nginx Plus
- Nginx Open Source — ฟรี มี reverse proxy, load balancing, SSL/TLS ครบ เพียงพอสำหรับ 90% ของ use cases
- Nginx Plus — เสียเงิน ($2,500/year) มี active health checks, session persistence, live activity monitoring, dynamic reconfiguration
สำหรับบทความนี้จะใช้ Open Source version ซึ่งเพียงพอสำหรับ production
ติดตั้งจาก Official Repository
# Ubuntu 22.04/24.04
# เพิ่ม Nginx official repository (ได้ version ล่าสุด)
curl -fsSL https://nginx.org/keys/nginx_signing.key | sudo gpg --dearmor -o /usr/share/keyrings/nginx-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] http://nginx.org/packages/mainline/ubuntu $(lsb_release -cs) nginx" | sudo tee /etc/apt/sources.list.d/nginx.list
# ให้ priority สูงกว่า Ubuntu default
echo -e "Package: *\nPin: origin nginx.org\nPin-Priority: 900" | sudo tee /etc/apt/preferences.d/99nginx
sudo apt update
sudo apt install -y nginx
# ตรวจสอบ version
nginx -v
# nginx version: nginx/1.25.4
# Start + Enable
sudo systemctl enable --now nginx
ผมเคยเขียนเรื่องที่เกี่ยวข้องไว้ใน load balancer nginx คอ
🎬 วิดีโอที่เกี่ยวข้อง — YouTube @icafefx
Reverse Proxy — พื้นฐานที่ต้องเข้าใจ
Reverse Proxy คือ server ที่รับ request จาก client แล้ว forward ไปยัง backend server จากนั้นส่ง response กลับให้ client โดยที่ client ไม่รู้ว่ามี backend server อยู่เบื้องหลัง
ทำไมต้องใช้ Reverse Proxy?
- SSL Termination — จัดการ SSL/TLS ที่จุดเดียว ไม่ต้องติดตั้ง cert บนทุก backend
- Load Balancing — กระจาย traffic ไปหลาย backend servers
- Caching — cache response ลด load บน backend
- Compression — compress response ก่อนส่งให้ client
- Security — ซ่อน backend servers จาก internet, rate limiting, WAF
- Static Files — serve static files โดยไม่ต้องผ่าน backend
Basic Reverse Proxy Config
# /etc/nginx/conf.d/app.conf
server {
listen 80;
server_name app.example.com;
# Redirect HTTP → HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name app.example.com;
# SSL Certificate
ssl_certificate /etc/letsencrypt/live/app.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem;
# SSL Settings (modern)
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# HSTS
add_header Strict-Transport-Security "max-age=63072000" always;
# Proxy to backend
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
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_set_header Connection "";
# Timeouts
proxy_connect_timeout 5s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# Buffering
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 4k;
}
# Static files — serve โดยตรง ไม่ผ่าน backend
location /static/ {
alias /var/www/app/static/;
expires 30d;
add_header Cache-Control "public, immutable";
}
# Health check endpoint
location /health {
access_log off;
return 200 "OK";
}
}
มาอธิบาย headers ที่สำคัญ:
X-Real-IP— IP จริงของ client (ไม่ใช่ IP ของ Nginx)X-Forwarded-For— chain ของ IPs ที่ request ผ่านมาX-Forwarded-Proto— protocol ที่ client ใช้ (http/https) สำคัญมากเพราะ backend ต้องรู้ว่า client ใช้ HTTPSConnection ""— ใช้ keepalive กับ backend
ผู้เชี่ยวชาญแนะนำ - siamlancard
แนะนำ: | |
Load Balancing — กระจาย Traffic อย่างมืออาชีพ
Upstream Block
# /etc/nginx/conf.d/upstream.conf
upstream backend_servers {
# Load balancing algorithm
least_conn;
# Backend servers
server 10.0.1.10:3000 weight=5 max_fails=3 fail_timeout=30s;
server 10.0.1.11:3000 weight=3 max_fails=3 fail_timeout=30s;
server 10.0.1.12:3000 weight=2 max_fails=3 fail_timeout=30s;
# Backup server — ใช้เมื่อ primary ทั้งหมดล่ม
server 10.0.2.10:3000 backup;
# Keepalive connections to backend
keepalive 32;
keepalive_requests 1000;
keepalive_timeout 60s;
}
server {
listen 443 ssl http2;
server_name app.example.com;
location / {
proxy_pass http://backend_servers;
proxy_http_version 1.1;
proxy_set_header Connection "";
# ... other proxy headers
}
}
Load Balancing Algorithms
1. Round Robin (default)
upstream backend {
server 10.0.1.10:3000;
server 10.0.1.11:3000;
server 10.0.1.12:3000;
}
# Request 1 → .10, Request 2 → .11, Request 3 → .12, Request 4 → .10 ...
เหมาะกับ: backend servers ที่มี spec เหมือนกัน, stateless applications
2. Weighted Round Robin
upstream backend {
server 10.0.1.10:3000 weight=5; # ได้ 5 ส่วน
server 10.0.1.11:3000 weight=3; # ได้ 3 ส่วน
server 10.0.1.12:3000 weight=2; # ได้ 2 ส่วน
}
# Server .10 ได้ traffic 50%, .11 ได้ 30%, .12 ได้ 20%
เหมาะกับ: backend servers ที่มี spec ต่างกัน
3. Least Connections
upstream backend {
least_conn;
server 10.0.1.10:3000;
server 10.0.1.11:3000;
server 10.0.1.12:3000;
}
ส่ง request ไปยัง server ที่มี active connections น้อยที่สุด เหมาะกับ: requests ที่ใช้เวลาต่างกันมาก เช่น file uploads, long-running queries
4. IP Hash
upstream backend {
ip_hash;
server 10.0.1.10:3000;
server 10.0.1.11:3000;
server 10.0.1.12:3000;
}
Client IP เดียวกันจะไปยัง server เดิมเสมอ (sticky sessions) เหมาะกับ: applications ที่เก็บ session ใน memory (ไม่แนะนำ — ควรใช้ Redis session store แทน)
5. Hash (Custom Key)
upstream backend {
hash $request_uri consistent;
server 10.0.1.10:3000;
server 10.0.1.11:3000;
server 10.0.1.12:3000;
}
Hash ด้วย key ที่กำหนดเอง consistent ทำให้เมื่อเพิ่ม/ลด server มีแค่ 1/N ของ requests ที่ถูก remap เหมาะกับ: caching layers ที่ต้องการ cache hit rate สูง
อ่านต่อ: reverse proxy nginx คอ
Health Checks และ Failover
Passive Health Checks (Open Source)
upstream backend {
server 10.0.1.10:3000 max_fails=3 fail_timeout=30s;
server 10.0.1.11:3000 max_fails=3 fail_timeout=30s;
server 10.0.1.12:3000 max_fails=3 fail_timeout=30s;
}
max_fails=3 — ถ้า fail 3 ครั้งติดต่อกัน จะมาร์ค server เป็น unavailable
fail_timeout=30s — หลังจากมาร์ค unavailable จะรอ 30 วินาทีก่อนลองใหม่
Passive health check ตรวจจับ failure เมื่อ request จริงล้มเหลว ข้อเสียคือ user บางคนจะเจอ error ก่อนที่ server จะถูกมาร์คเป็น unavailable
Active Health Checks (ใช้ Module เสริม)
สำหรับ Nginx Open Source ใช้ nginx_upstream_check_module หรือ compile กับ ngx_http_healthcheck_module:
# ใช้ร่วมกับ proxy_next_upstream เพื่อ retry อัตโนมัติ
location / {
proxy_pass http://backend;
proxy_next_upstream error timeout http_502 http_503 http_504;
proxy_next_upstream_timeout 10s;
proxy_next_upstream_tries 3;
}
proxy_next_upstream ทำให้เมื่อ backend ตอบ error, Nginx จะลอง backend ถัดไปอัตโนมัติ user ไม่เห็น error เลย
อ่านต่อ: nginx reverse proxy คอ
Caching — ลด Backend Load 90%
# /etc/nginx/conf.d/cache.conf
# กำหนด cache zone
proxy_cache_path /var/cache/nginx/app
levels=1:2
keys_zone=app_cache:100m
max_size=10g
inactive=60m
use_temp_path=off;
server {
listen 443 ssl http2;
server_name app.example.com;
# เปิด cache
proxy_cache app_cache;
proxy_cache_key "$scheme$request_method$host$request_uri";
proxy_cache_valid 200 10m;
proxy_cache_valid 404 1m;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
proxy_cache_background_update on;
proxy_cache_lock on;
# แสดง cache status ใน response header
add_header X-Cache-Status $upstream_cache_status;
location / {
proxy_pass http://backend_servers;
# ไม่ cache requests ที่มี cookie
proxy_cache_bypass $cookie_session;
proxy_no_cache $cookie_session;
}
# API — ไม่ cache
location /api/ {
proxy_pass http://backend_servers;
proxy_cache off;
}
# Static assets — cache นาน
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2)$ {
proxy_pass http://backend_servers;
proxy_cache_valid 200 30d;
expires 30d;
add_header Cache-Control "public, immutable";
}
}
อธิบาย directives สำคัญ:
proxy_cache_use_stale— ถ้า backend ล่ม ให้ serve cached content เก่าแทน (สำคัญมาก!)proxy_cache_background_update— update cache ใน background ไม่ block userproxy_cache_lock— ถ้ามีหลาย requests มาพร้อมกันสำหรับ key เดียวกัน ให้แค่ 1 request ไปถึง backend ที่เหลือรอ cache
จากประสบการณ์จริง cache ช่วยลด backend load ได้ 80-95% สำหรับ content-heavy websites
Rate Limiting — ป้องกัน DDoS และ Abuse
# กำหนด rate limit zones
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=login_limit:10m rate=1r/s;
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
server {
# Connection limit
limit_conn conn_limit 20;
# API rate limit
location /api/ {
limit_req zone=api_limit burst=20 nodelay;
limit_req_status 429;
proxy_pass http://backend_servers;
}
# Login — strict rate limit
location /api/auth/login {
limit_req zone=login_limit burst=5 nodelay;
limit_req_status 429;
proxy_pass http://backend_servers;
}
}
rate=10r/s — อนุญาต 10 requests ต่อวินาทีต่อ IP
burst=20 — อนุญาต burst ได้อีก 20 requests (จะถูก queue)
nodelay — ไม่ delay burst requests ให้ process ทันที
limit_req_status 429 — return HTTP 429 Too Many Requests
WebSocket Proxy
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
location /ws/ {
proxy_pass http://websocket_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
# WebSocket timeout (ต้องยาวกว่า HTTP ปกติ)
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
}
WebSocket ต้องการ HTTP Upgrade header ถ้าไม่ตั้ง proxy_read_timeout ให้ยาวพอ Nginx จะตัด connection หลัง 60 วินาที (default)
📌 บทความแนะนำจาก siamlancard: | |
HTTP/3 QUIC — อนาคตของ Web
# Nginx 1.25.0+ รองรับ HTTP/3
server {
listen 443 ssl;
listen 443 quic reuseport;
http2 on;
http3 on;
server_name app.example.com;
ssl_certificate /etc/letsencrypt/live/app.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem;
# HTTP/3 requires TLS 1.3
ssl_protocols TLSv1.2 TLSv1.3;
# บอก client ว่ารองรับ HTTP/3
add_header Alt-Svc 'h3=":443"; ma=86400';
location / {
proxy_pass http://backend_servers;
}
}
HTTP/3 ใช้ QUIC protocol (UDP-based) แทน TCP ทำให้:
- Connection establishment เร็วขึ้น (0-RTT)
- ไม่มี head-of-line blocking
- Connection migration (เปลี่ยน network ได้โดยไม่ต้อง reconnect)
Production nginx.conf ที่ใช้จริง
# /etc/nginx/nginx.conf
user www-data;
worker_processes auto;
worker_rlimit_nofile 65535;
pid /run/nginx.pid;
events {
worker_connections 65535;
multi_accept on;
use epoll;
}
http {
# === Basic ===
sendfile on;
tcp_nopush on;
tcp_nodelay on;
types_hash_max_size 2048;
server_tokens off; # ซ่อน Nginx version
# === Timeouts ===
keepalive_timeout 65;
keepalive_requests 1000;
client_body_timeout 12;
client_header_timeout 12;
send_timeout 10;
# === Buffer ===
client_body_buffer_size 16k;
client_header_buffer_size 1k;
client_max_body_size 50m;
large_client_header_buffers 4 8k;
# === Gzip ===
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 4;
gzip_min_length 256;
gzip_types
text/plain
text/css
text/javascript
application/javascript
application/json
application/xml
image/svg+xml
font/woff2;
# === Logging ===
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$request_time $upstream_response_time '
'$upstream_cache_status';
access_log /var/log/nginx/access.log main buffer=32k flush=5s;
error_log /var/log/nginx/error.log warn;
# === Security Headers ===
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# === Includes ===
include /etc/nginx/mime.types;
default_type application/octet-stream;
include /etc/nginx/conf.d/*.conf;
}
Troubleshooting ปัญหาที่พบบ่อย
ปัญหา 1: 502 Bad Gateway
# สาเหตุ: backend ไม่ตอบ หรือ connection refused
# ตรวจสอบ:
sudo tail -f /var/log/nginx/error.log
# "connect() failed (111: Connection refused) while connecting to upstream"
# แก้: ตรวจสอบว่า backend ทำงานอยู่
curl -v http://127.0.0.1:3000/health
systemctl status myapp
ปัญหา 2: 504 Gateway Timeout
# สาเหตุ: backend ตอบช้าเกินไป
# แก้: เพิ่ม timeout
proxy_connect_timeout 10s;
proxy_send_timeout 120s;
proxy_read_timeout 120s;
ปัญหา 3: worker_connections are not enough
# แก้: เพิ่ม worker_connections และ file descriptors
worker_rlimit_nofile 65535;
events {
worker_connections 65535;
}
# ตรวจสอบ current connections
ss -s
nginx -T | grep worker
คำถามที่พบบ่อย (FAQ)
Q: Nginx กับ HAProxy เลือกอะไรดี?
A: Nginx เหมาะกับ web traffic (HTTP/HTTPS) + static files + caching HAProxy เหมาะกับ TCP load balancing + advanced health checks ถ้าเป็น web app ใช้ Nginx ถ้าเป็น database/TCP ใช้ HAProxy
Q: worker_processes ตั้งเท่าไหร่?
A: ใช้ auto ให้ Nginx ตั้งตาม CPU cores ถ้า server มี 4 cores จะได้ 4 workers
Q: ใช้กับ Docker ยังไง?
A: ใช้ official image nginx:alpine mount config เข้าไป:
docker run -d -p 80:80 -p 443:443 \
-v /etc/nginx/conf.d:/etc/nginx/conf.d:ro \
-v /etc/letsencrypt:/etc/letsencrypt:ro \
nginx:alpine
Q: Let's Encrypt กับ Nginx ตั้งยังไง?
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d app.example.com
# Auto-renew ทุก 12 ชั่วโมง
echo "0 */12 * * * root certbot renew --quiet" | sudo tee /etc/cron.d/certbot
Q: ทำ A/B Testing ด้วย Nginx ได้ไหม?
# ใช้ split_clients module
split_clients "${remote_addr}" $variant {
50% backend_v1;
* backend_v2;
}
location / {
proxy_pass http://$variant;
}
Q: Nginx กับ Cloudflare ใช้ด้วยกันยังไง?
A: ตั้ง Cloudflare เป็น DNS proxy → Nginx รับ traffic จาก Cloudflare ต้องตั้ง set_real_ip_from เพื่อให้ได้ IP จริงของ client:
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
# ... (Cloudflare IP ranges)
real_ip_header CF-Connecting-IP;
สรุป — Nginx คือ Must-Have สำหรับทุก Production
Nginx เป็น reverse proxy และ load balancer ที่ดีที่สุดสำหรับ web traffic ด้วย performance สูง config ที่ยืดหยุ่น และ community ที่ใหญ่มาก เริ่มจาก basic reverse proxy ก่อน จากนั้นเพิ่ม load balancing, caching, rate limiting ตามความต้องการ ภายใน 1 ชั่วโมงคุณจะมี production-ready setup
ถ้ามีคำถาม สอบถามได้ที่ SiamCafe Forum ครับ
💡 เรียนรู้เพิ่มเติม: | | — จาก ผู้เชี่ยวชาญประสบการณ์กว่า 13 ปี
🎬 ดูวิดีโอเพิ่มเติม
เรียนรู้ IT, Forex Trading และเทคนิค Server จากประสบการณ์จริง 30 ปี