ตั้ง Nginx เป็น Reverse Proxy พร้อม Cache ลดภาระ Backend
เมื่อเว็บมีผู้ใช้มากขึ้น คอขวดมักไม่ได้อยู่ที่ Nginx แต่อยู่ที่ Backend ที่ต้องประมวลผลและคิวรีฐานข้อมูลทุกคำขอ ทั้งที่หน้าเว็บจำนวนมากให้ผลเหมือนกันกับทุกคน การให้ Nginx เก็บผลลัพธ์ไว้ตอบซ้ำจึงลดภาระได้มากโดยไม่ต้องแก้โค้ด
คู่มือนี้ตั้ง Nginx เป็น Reverse Proxy หน้า Backend ไม่ว่าจะเป็น PHP-FPM, Node.js หรือ Container แล้วเปิดแคชอย่างปลอดภัย พร้อมกฎที่ต้องระวังเพื่อไม่ให้ผู้ใช้เห็นข้อมูลของคนอื่น
สิ่งที่ต้องเตรียม
- Nginx บน Linux และสิทธิ์
sudo - Backend ที่ทำงานอยู่แล้ว เช่น แอปที่ฟังพอร์ต 3000 บน localhost
- พื้นที่ดิสก์สำหรับเก็บแคช เริ่มที่ 1-2 GB ก็เพียงพอสำหรับเว็บทั่วไป
ขั้นตอนที่ 1: ตั้ง Reverse Proxy พื้นฐานก่อน
sudo nano /etc/nginx/sites-available/example.com
upstream app_backend {
server 127.0.0.1:3000;
keepalive 32;
}
server {
listen 443 ssl;
http2 on;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
location / {
proxy_pass http://app_backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
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_read_timeout 60s;
}
}
sudo nginx -t && sudo systemctl reload nginx
ส่วน keepalive 32 คู่กับ proxy_set_header Connection "" ทำให้ Nginx ใช้การเชื่อมต่อเดิมซ้ำกับ Backend แทนที่จะเปิดใหม่ทุกคำขอ ซึ่งช่วยลดภาระได้มากในเว็บที่มีทราฟฟิกสูง
ขั้นตอนที่ 2: ประกาศพื้นที่เก็บแคช
ประกาศในบล็อก http ไม่ใช่ใน server
sudo nano /etc/nginx/nginx.conf
proxy_cache_path /var/cache/nginx/app
levels=1:2
keys_zone=app_cache:20m
max_size=2g
inactive=60m
use_temp_path=off;
sudo mkdir -p /var/cache/nginx/app
sudo chown www-data:www-data /var/cache/nginx/app
ความหมายของค่าแต่ละตัว keys_zone=app_cache:20m คือพื้นที่หน่วยความจำสำหรับเก็บกุญแจ ซึ่ง 20 MB เก็บได้ราวหนึ่งแสนหกหมื่นรายการ max_size=2g คือเพดานพื้นที่บนดิสก์ และ inactive=60m คือรายการที่ไม่ถูกเรียกเลยใน 60 นาทีจะถูกลบทิ้ง
ขั้นตอนที่ 3: เปิดแคชอย่างปลอดภัย
map $http_cookie $skip_cache {
default 0;
# ผู้ใช้ที่ล็อกอินอยู่ต้องไม่ถูกแคช
~*session_id 1;
~*wordpress_logged_in 1;
~*laravel_session 1;
}
map $request_method $skip_cache_method {
default 1;
GET 0;
HEAD 0;
}
server {
# ... ส่วนเดิม ...
location / {
proxy_pass http://app_backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
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_cache app_cache;
proxy_cache_key "$scheme$request_method$host$request_uri";
proxy_cache_valid 200 301 302 10m;
proxy_cache_valid 404 1m;
proxy_cache_bypass $skip_cache $skip_cache_method $arg_nocache;
proxy_no_cache $skip_cache $skip_cache_method;
# ใช้แคชเดิมตอบต่อได้หาก Backend ล่มหรือช้า
proxy_cache_use_stale error timeout updating
http_500 http_502 http_503 http_504;
proxy_cache_background_update on;
proxy_cache_lock on;
add_header X-Cache-Status $upstream_cache_status always;
}
}
sudo nginx -t && sudo systemctl reload nginx
ขั้นตอนที่ 4: เข้าใจสามบรรทัดที่สำคัญที่สุด
- proxy_cache_use_stale ทำให้เว็บยังเปิดได้แม้ Backend ล่ม โดยตอบจากแคชเดิมที่หมดอายุแล้ว ผู้ใช้เห็นข้อมูลเก่าเล็กน้อยดีกว่าเห็นหน้า 502
- proxy_cache_lock ป้องกันปัญหาที่เมื่อแคชหมดอายุพร้อมกัน คำขอหลายร้อยรายการวิ่งไป Backend พร้อมกันจนล่ม เมื่อเปิดไว้จะมีคำขอเดียวที่ไปดึงของใหม่ ที่เหลือรอผลนั้น
- X-Cache-Status คือ header ที่ให้คุณตรวจสอบได้ว่าคำขอนั้นถูกตอบจากแคชหรือไม่ ควรมีไว้เสมอตอนตั้งค่า
ขั้นตอนที่ 5: ทดสอบว่าแคชทำงาน
curl -sI https://example.com/ | grep -i x-cache-status
curl -sI https://example.com/ | grep -i x-cache-status
ครั้งแรกควรได้ MISS ครั้งที่สองควรได้ HIT ค่าอื่นที่พบได้คือ BYPASS เมื่อตรงเงื่อนไขข้าม EXPIRED เมื่อหมดอายุและกำลังดึงใหม่ และ STALE เมื่อตอบด้วยของเก่าเพราะ Backend มีปัญหา
ทดสอบว่าผู้ใช้ที่ล็อกอินไม่โดนแคช
curl -sI -H 'Cookie: wordpress_logged_in_abc=1' https://example.com/ | grep -i x-cache-status
ควรได้ BYPASS หากได้ HIT แปลว่ากฎยังไม่ถูกต้องและมีความเสี่ยงที่ผู้ใช้จะเห็นหน้าของคนอื่น ต้องแก้ทันที
ขั้นตอนที่ 6: เพิ่มกฎสำหรับไฟล์คงที่
location ~* \.(?:css|js|woff2|png|jpe?g|gif|svg|webp|ico)$ {
proxy_pass http://app_backend;
proxy_cache app_cache;
proxy_cache_valid 200 30d;
proxy_cache_key "$scheme$request_method$host$request_uri";
add_header X-Cache-Status $upstream_cache_status always;
add_header Cache-Control "public, max-age=2592000, immutable";
}
ไฟล์ที่มีชื่อพร้อมรหัสรุ่น เช่น app.4f3a2b.js แคชได้ยาวเพราะเปลี่ยนเนื้อหาเมื่อไรชื่อไฟล์ก็เปลี่ยนตาม
ขั้นตอนที่ 7: ล้างแคช
Nginx รุ่นโอเพนซอร์สไม่มีคำสั่งล้างแคชรายหน้าในตัว วิธีที่ใช้ได้จริงมีสองทาง
# ล้างทั้งหมด
sudo rm -rf /var/cache/nginx/app/*
sudo systemctl reload nginx
# ล้างเฉพาะหน้าเดียว โดยคำนวณกุญแจแล้วหาไฟล์
KEY="httpsGETexample.com/about/"
HASH=$(printf '%s' "$KEY" | md5sum | cut -d' ' -f1)
sudo find /var/cache/nginx/app -name "$HASH" -delete
อีกทางคือใช้ตัวแปร $arg_nocache ที่ตั้งไว้ในขั้นตอนที่ 3 เรียกหน้าด้วย ?nocache=1 เพื่อบังคับดึงของใหม่มาเก็บทับ
ขั้นตอนที่ 8: เฝ้าดูว่าแคชได้ผลแค่ไหน
sudo nano /etc/nginx/nginx.conf
log_format cached '$remote_addr - $upstream_cache_status '
'"$request" $status $body_bytes_sent '
'$request_time';
access_log /var/log/nginx/access.log cached;
sudo awk '{print $4}' /var/log/nginx/access.log | sort | uniq -c | sort -rn
sudo du -sh /var/cache/nginx/app
อัตรา HIT ที่ดีสำหรับเว็บเนื้อหาทั่วไปคือ 70% ขึ้นไป หากต่ำกว่านั้นมาก ให้ตรวจว่ากฎข้ามแคชกว้างเกินไปหรือไม่ และ proxy_cache_valid สั้นเกินไปหรือเปล่า
ปัญหาที่พบบ่อย
ได้ MISS ทุกครั้ง
สาเหตุที่พบบ่อยคือ Backend ส่ง header Cache-Control: no-cache หรือ Set-Cookie กลับมาทุกคำขอ ซึ่ง Nginx จะไม่แคชให้โดยอัตโนมัติ ตรวจด้วย curl -sI http://127.0.0.1:3000/ หากจำเป็นให้สั่งเพิกเฉยด้วย proxy_ignore_headers Cache-Control Expires Set-Cookie; แต่ต้องมั่นใจว่าหน้านั้นไม่มีข้อมูลส่วนบุคคล
ผู้ใช้เห็นข้อมูลของคนอื่น
เป็นปัญหาร้ายแรงที่สุดของการแคช เกิดจากหน้าที่มีข้อมูลเฉพาะบุคคลถูกแคชไว้ ตรวจกฎ proxy_cache_bypass ให้ครอบคลุมคุกกี้ของระบบล็อกอินทั้งหมด และเพิ่มคุกกี้ผู้ใช้เข้าไปใน proxy_cache_key หากจำเป็น
แก้เนื้อหาแล้วหน้าเว็บยังเป็นของเดิม
ปกติของการแคช รอจนหมดอายุตาม proxy_cache_valid หรือล้างแคชตามขั้นตอนที่ 7 หากต้องล้างบ่อยให้ตั้งระบบล้างอัตโนมัติเมื่อมีการบันทึกเนื้อหา
ดิสก์เต็มเพราะแคช
ตรวจว่า max_size ถูกตั้งไว้แล้ว และค่านั้นน้อยกว่าพื้นที่ว่างจริง Nginx จะลบรายการที่เก่าที่สุดเองเมื่อถึงเพดาน
ต้องการให้ทีมวิศวกรช่วยปรับโครงสร้างให้รองรับทราฟฟิกสูง ติดต่อ THAI DATA CLOUD ได้ที่ https://thaidata.cloud/contact/
- Categories:
- Cloud
- Tags:
- Cloud
- Cloud Server
Related Posts
หมวดหมู่ที่น่าสนใจ
- Account Settings
- AD Server
- AI
- Alibaba Cloud
- Anti-Spam Gateway
- AWS Amazon Web Services
- Campaign
- CentOS/AlmaLinux
- Cloud
- Cloud Backup
- Cloud Communication
- Cloud Migration
- Cloud Security
- Cloud Server Management
- Cloud Solution
- Cloud Solution for Government
- Cloud Solutions by Industry
- Cloud Storage
- Cloud VPS App Plus +
- Cloud VPS DirectAdmin
- Cloud VPS Plesk
- CSR
- Cyber Security
- Cybersecurity
- Data Sovereignty
- Database Server
- DDoS
- Digital Tranformation
- Digital Transformation
- Direct Mail
- Directadmin
- Domainname
- Ecommerce
- ERP
- Generative AI
- Getting Started
- Google Cloud
- Google G Suite
- Huawei Cloud
- IT News
- Linux Server
- Managed Cloud Services
- Managed Service Provider
- Manual
- Microsoft
- Microsoft 365
- Microsoft Azure
- News
- On-premise
- Private Mail Server
- Promotion
- Recommend Solution (Enterprise)
- Server
- Sovereign Cloud
- THAI DATA CLOUD Platform
- Ubuntu
- Ubuntu
- Uncategorized
- VMware
- VPS Server
- Web Design
- Web Hosting
- Web Hosting (DirectAdmin)
- Web Hosting (Plesk)
- Web Technologies
- Windows Server
- Wordpress
- Zimbra
- เรื่องราวความประทับใจ
- โซลูชันสำหรับธุรกิจการผลิตและยานยนต์
- โซลูชันสำหรับธุรกิจการศึกษา
- โซลูชันสำหรับธุรกิจการเงิน
- โซลูชันสำหรับธุรกิจขนส่งและกระจายสินค้า
- โซลูชันสำหรับธุรกิจค้าปลีก
- โซลูชันสำหรับธุรกิจท่องเที่ยว
- โซลูชันสำหรับธุรกิจบริการสุขภาพและโรงพยาบาล
- โซลูชันสำหรับธุรกิจประกันภัย
- โซลูชันสำหรับธุรกิจพลังงานและสาธารณูปโภค
- โซลูชันสำหรับธุรกิจสื่อสารมวลชนและเอ็นเตอร์เทนเมนท์
- โซลูชันสำหรับธุรกิจอสังหาริมทรัพย์
- โซลูชันสำหรับธุรกิจเทคโนโลยี








