คำตอบสั้น ๆ: ปรับค่าเคอร์เนลที่จำเป็นจริงสำหรับเว็บเซิร์ฟเวอร์ที่รับการเชื่อมต่อจำนวนมาก พร้อมอธิบายว่าแต่ละค่าทำอะไรและเมื่อไรจึงควรแตะ
คู่มือนี้อธิบาย sysctl ทีละขั้นตอน พร้อมคำสั่งที่ใช้ได้จริงและปัญหาที่พบบ่อย
ค่าเริ่มต้นของเคอร์เนล Linux ถูกตั้งมาให้ปลอดภัยกับเครื่องทุกขนาด ตั้งแต่อุปกรณ์ฝังตัวไปจนถึงเซิร์ฟเวอร์ใหญ่ เมื่อเซิร์ฟเวอร์ของคุณเริ่มรับการเชื่อมต่อพร้อมกันหลักพัน ค่าบางตัวจะกลายเป็นเพดานที่มองไม่เห็น อาการที่เห็นคือ connection refused หรือเว็บหน่วงเป็นช่วง ทั้งที่ CPU และ RAM ยังเหลือ
คู่มือนี้อธิบายค่าที่ควรปรับจริงสำหรับเว็บเซิร์ฟเวอร์ พร้อมเหตุผลของแต่ละตัว และที่สำคัญคือบอกด้วยว่าค่าไหน "ไม่ควรแตะ" แม้จะเห็นแนะนำกันมากในอินเทอร์เน็ต
สิ่งที่ต้องเตรียม
- Linux Server และสิทธิ์
sudo - รู้ปริมาณการใช้งานจริงคร่าว ๆ เช่น จำนวนการเชื่อมต่อพร้อมกันสูงสุด ดูได้จาก
ss -s
หลักสำคัญ อย่าคัดลอกชุดค่าจากอินเทอร์เน็ตมาใส่ทั้งก้อน ปรับทีละกลุ่มแล้ววัดผล ค่าที่เหมาะกับเครื่อง 64 GB ไม่เหมาะกับเครื่อง 2 GB
ขั้นตอนที่ 1: ดูค่าปัจจุบันก่อน
sysctl net.core.somaxconn
sysctl net.ipv4.ip_local_port_range
sysctl fs.file-max
sysctl vm.swappiness
# ดูทั้งหมด
sudo sysctl -a | less
จดค่าเดิมไว้ก่อนแก้เสมอ วิธีที่ง่ายที่สุดคือบันทึกลงไฟล์
sudo sysctl -a > /root/sysctl-before-$(date +%F).txt
ขั้นตอนที่ 2: สร้างไฟล์ตั้งค่าของเราเอง
อย่าแก้ /etc/sysctl.conf ตรง ๆ เพราะการอัปเดตระบบอาจเขียนทับ ให้สร้างไฟล์แยกใน /etc/sysctl.d/ ซึ่งโหลดตามลำดับตัวเลขนำหน้า
sudo nano /etc/sysctl.d/99-tdc-tuning.conf
ขั้นตอนที่ 3: ค่าเกี่ยวกับการรับการเชื่อมต่อ
# คิวของการเชื่อมต่อที่รอให้แอปรับ (Nginx, MySQL)
net.core.somaxconn = 4096
# คิวของการเชื่อมต่อที่ยังจับมือ TCP ไม่เสร็จ
net.ipv4.tcp_max_syn_backlog = 8192
# คิวแพ็กเก็ตขาเข้าที่รอเคอร์เนลประมวลผล
net.core.netdev_max_backlog = 5000
somaxconn คือค่าที่สำคัญที่สุดในกลุ่มนี้ ค่าเริ่มต้นเดิมคือ 128 ซึ่งต่ำมากสำหรับเว็บที่มีคนเข้าพร้อมกัน เมื่อคิวเต็ม การเชื่อมต่อใหม่จะถูกปฏิเสธทันที ผู้ใช้เห็นเป็นหน้าเว็บโหลดไม่ขึ้นเป็นช่วง
สำคัญ การเพิ่มค่านี้อย่างเดียวไม่พอ ต้องบอกแอปให้ใช้ค่าที่สูงขึ้นด้วย ใน Nginx ตั้งที่บรรทัด listen
listen 443 ssl backlog=4096;
ขั้นตอนที่ 4: ค่าเกี่ยวกับพอร์ตและการเชื่อมต่อที่ปิดแล้ว
# ช่วงพอร์ตที่ใช้เป็นต้นทางของการเชื่อมต่อขาออก
net.ipv4.ip_local_port_range = 10240 65535
# นำพอร์ตในสถานะ TIME_WAIT กลับมาใช้ใหม่ได้เร็วขึ้น
net.ipv4.tcp_tw_reuse = 1
# ลดเวลารอปิดการเชื่อมต่อฝั่งที่ค้าง
net.ipv4.tcp_fin_timeout = 15
ค่าเหล่านี้มีผลเมื่อเซิร์ฟเวอร์ของคุณเป็นฝั่งที่ เปิด การเชื่อมต่อออกไปเยอะ เช่น Reverse Proxy ที่ยิงต่อไปยัง Backend หรือแอปที่เรียก API ภายนอกถี่ ๆ อาการเมื่อพอร์ตหมดคือ cannot assign requested address
ตรวจจำนวน TIME_WAIT ปัจจุบันได้ด้วย
ss -tan state time-wait | wc -l
อย่าเปิด net.ipv4.tcp_tw_recycle ค่านี้สร้างปัญหากับผู้ใช้ที่อยู่หลัง NAT เดียวกันและถูกถอดออกจากเคอร์เนลรุ่นใหม่แล้ว คำแนะนำเก่า ๆ ในอินเทอร์เน็ตยังมีอยู่มาก
ขั้นตอนที่ 5: ค่าเกี่ยวกับจำนวนไฟล์ที่เปิดได้
# เพดานทั้งระบบ
fs.file-max = 2097152
# จำนวน inotify watch (สำคัญกับ Docker และตัวเฝ้าไฟล์)
fs.inotify.max_user_watches = 524288
ค่า fs.file-max เป็นเพดานรวมของทั้งเครื่อง แต่ยังมีเพดานรายโปรเซสที่ควบคุมด้วย ulimit และ systemd อีกชั้น ต้องตั้งทั้งสองที่จึงจะได้ผล ดูวิธีตั้งฝั่ง systemd ได้ในคู่มือเรื่อง Too many open files