❤️ AZDIGI chính thức cập nhật hệ thống blog mới hoàn chỉnh. Tuy nhiên có thể một số bài viết bị sai lệch hình ảnh, hãy ấn nút Báo cáo bài viết ở cuối bài để AZDIGI cập nhật trong thời gian nhanh nhất. Chân thành cám ơn.
Web stack Nginx + PHP-FPM + MySQL là combo phổ biến nhất hiện nay. Nếu tối ưu đúng cách, tốc độ website có thể tăng gấp đôi, thậm chí gấp ba. Bài này sẽ hướng dẫn chi tiết từ cấu hình Nginx, PHP-FPM đến kiểm tra hiệu quả thực tế.
Tại sao cần tối ưu Nginx và PHP-FPM?

Nginx làm web server đầu cuối, nhận request từ người dùng. PHP-FPM xử lý code PHP. Mặc định, cả hai đều cấu hình bảo thủ để đảm bảo ổn định. Nhưng với VPS có cấu hình tốt, bạn có thể đẩy mạnh hiệu năng mà không lo crash.
Dấu hiệu VPS cần tối ưu:
- Load time trên 2 giây
- CPU thường xuyên cao
- RAM sử dụng dưới 80% nhưng website vẫn chậm
- Nginx error log có nhiều “worker_connections are not enough”
Tối ưu Nginx cơ bản
Cấu hình worker processes
Worker processes là số tiến trình Nginx chạy song song. Công thức đơn giản:
# /etc/nginx/nginx.conf
worker_processes auto; # Nginx tự động = số CPU cores
Kiểm tra số CPU cores:
nproc # Ví dụ output: 4
💡 Với VPS 4 cores, Nginx sẽ tạo 4 worker processes. Mỗi worker xử lý khoảng 1000 connections đồng thời mặc định.
Tăng worker connections
events {
worker_connections 2048; # Mặc định 1024
use epoll; # Linux kernel 2.6+
}
VPS 4 cores với 2048 connections = 8192 connections đồng thời tối đa. Đủ cho website 50-100k pageviews/ngày.
Bật gzip compression
http {
# Gzip cơ bản
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_comp_level 6;
# Compress file types
gzip_types
text/plain
text/css
application/json
application/javascript
text/xml
application/xml
application/xml+rss
text/javascript
image/svg+xml;
}
Gzip giảm bandwidth 60-80% cho text files. Level 6 là cân bằng tốt giữa tốc độ và tỷ lệ nén.
HTTP/2 và SSL optimization
server {
listen 443 ssl http2;
# SSL session cache
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;
# SSL protocols
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
}
HTTP/2 cho phép multiplexing – gửi nhiều file cùng lúc qua 1 connection. Hiệu quả rõ rệt với website có nhiều CSS/JS.
Keepalive và timeouts
http {
# Keepalive
keepalive_timeout 30;
keepalive_requests 100;
# Client timeouts
client_body_timeout 12;
client_header_timeout 12;
send_timeout 10;
# Buffer sizes
client_body_buffer_size 10K;
client_header_buffer_size 1k;
client_max_body_size 8m;
large_client_header_buffers 2 1k;
}
Keepalive 30 giây cho phép reuse connection. Timeout ngắn tránh connection idle lâu làm cạn kiệt pool.
Static file caching
location ~* \.(jpg|jpeg|png|gif|ico|css|js|pdf|txt)$ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}
location ~* \.(html|htm)$ {
expires 1h;
add_header Cache-Control "public";
}
Static files cache 1 năm, HTML cache 1 giờ. Giảm request tới server đáng kể.
File cấu hình nginx.conf hoàn chỉnh
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 2048;
use epoll;
multi_accept on;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Logging
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
# Performance
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 30;
keepalive_requests 100;
types_hash_max_size 2048;
server_tokens off;
# Client settings
client_max_body_size 8M;
client_body_buffer_size 10k;
client_header_buffer_size 1k;
large_client_header_buffers 2 1k;
client_body_timeout 12;
client_header_timeout 12;
send_timeout 10;
# Gzip compression
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_comp_level 6;
gzip_types
text/plain
text/css
application/json
application/javascript
text/xml
application/xml
application/xml+rss
text/javascript
image/svg+xml;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
Tối ưu PHP-FPM chi tiết
Ba chế độ process management
PHP-FPM có 3 chế độ quản lý processes:
1. pm = static
pm = static
pm.max_children = 20
- Tạo 20 processes cố định, không thay đổi
- Ưu điểm: Response time ổn định, không có delay spawn process
- Nhược điểm: Tốn RAM liên tục
- Phù hợp: VPS RAM nhiều (4GB+), traffic cao ổn định
2. pm = dynamic
pm = dynamic
pm.max_children = 20
pm.start_servers = 5
pm.min_spare_servers = 3
pm.max_spare_servers = 8
- Bắt đầu 5 processes, tăng giảm theo traffic
- Luôn giữ 3-8 processes idle
- Ưu điểm: Cân bằng RAM và performance
- Nhược điểm: Có chút delay khi spawn process mới
- Phù hợp: VPS 2-4GB RAM, traffic thay đổi
3. pm = ondemand
pm = ondemand
pm.max_children = 20
pm.process_idle_timeout = 30s
- Chỉ spawn process khi có request
- Kill process sau 30s idle
- Ưu điểm: Tiết kiệm RAM tối đa
- Nhược điểm: Delay đầu mỗi burst traffic
- Phù hợp: VPS RAM ít (1-2GB), traffic thấp không đều
Tính toán pm.max_children
Công thức: pm.max_children = (RAM dành cho PHP) / (RAM trung bình mỗi worker)
Kiểm tra RAM trung bình mỗi PHP worker:
ps --no-headers -o rss -p $(pgrep -d, php-fpm) | awk '{sum+=$1} END {print sum/NR/1024 "MB"}'
Ví dụ output: 52.5MB
Với VPS 4GB, dành 2GB cho PHP:
pm.max_children = 2048MB / 52.5MB = 39
💡 Làm tròn xuống 35 để an toàn.
Cấu hình www.conf tối ưu
; /etc/php-fpm.d/www.conf
[www]
user = nginx
group = nginx
; Socket thay vì TCP port (nhanh hơn)
listen = /var/run/php-fpm/php-fpm.sock
listen.owner = nginx
listen.group = nginx
listen.mode = 0660
listen.allowed_clients = 127.0.0.1
; Process management cho VPS 4GB, traffic trung bình
pm = dynamic
pm.max_children = 35
pm.start_servers = 8
pm.min_spare_servers = 5
pm.max_spare_servers = 15
; Restart workers sau 500 requests (tránh memory leak)
pm.max_requests = 500
; Timeouts
request_terminate_timeout = 30
request_slowlog_timeout = 10
slowlog = /var/log/php-fpm/www-slow.log
; Status page để monitor
pm.status_path = /fpm-status
ping.path = /fpm-ping
; Security
security.limit_extensions = .php
; Environment variables
env[HOSTNAME] = $HOSTNAME
env[PATH] = /usr/local/bin:/usr/bin:/bin
env[TMP] = /tmp
env[TMPDIR] = /tmp
env[TEMP] = /tmp
Chú ý socket thay vì TCP. Trong Nginx virtual host:
location ~ \.php$ {
fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
Monitor PHP-FPM processes
# Xem tất cả PHP workers
ps aux | grep php-fpm
# Đếm số processes
pgrep php-fpm | wc -l
# Check status page (nếu đã config)
curl http://localhost/fpm-status
# Theo dõi real-time
watch -n1 'ps aux | grep php-fpm | wc -l'
Status page output:
pool: www
process manager: dynamic
start time: 25/Dec/2023:10:30:15 +0700
start since: 3600
accepted conn: 12543
listen queue: 0
max listen queue: 0
listen queue len: 0
idle processes: 8
active processes: 2
total processes: 10
⚠️ listen queue > 0 liên tục là dấu hiệu cần tăng pm.max_children.
Tối ưu OPcache
Tại sao cần OPcache
PHP là ngôn ngữ interpreted. Mỗi request, PHP compile từ source code thành bytecode rồi execute. OPcache cache bytecode trong RAM, bỏ qua bước compile.
Với website WordPress thông thường, OPcache giảm 30-50% CPU usage.
Cấu hình opcache.ini
; /etc/php.d/10-opcache.ini
[opcache]
zend_extension=opcache.so
; Enable OPcache
opcache.enable=1
opcache.enable_cli=0
; Memory settings
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=10000
; Revalidation
opcache.revalidate_freq=60
opcache.validate_timestamps=1
; Performance
opcache.save_comments=0
opcache.fast_shutdown=1
; File cache (optional backup)
opcache.file_cache=/tmp/opcache
opcache.file_cache_only=0
Giải thích tham số:
memory_consumption=128: 128MB RAM cho cachemax_accelerated_files=10000: Cache tối đa 10000 files PHPrevalidate_freq=60: Check file thay đổi mỗi 60 giây (production)validate_timestamps=1: Enable revalidation (dev environment nên để 1, production có thể để 0)
Kiểm tra OPcache status
Tạo file PHP check:
<?php
// opcache-status.php
echo "<pre>";
print_r(opcache_get_status());
echo "</pre>";
echo "<h3>Configuration:</h3>";
echo "<pre>";
print_r(opcache_get_configuration());
echo "</pre>";
?>
Output quan trọng:
[opcache_enabled] => 1
[cache_full] => 0
[restart_pending] => 0
[restart_in_progress] => 0
[memory_usage] => Array
[used_memory] => 89543168
[free_memory] => 44456832
[wasted_memory] => 0
[opcache_statistics] => Array
[num_cached_scripts] => 847
[hits] => 124543
[misses] => 1543
[blacklist_misses] => 0
hits/(hits+misses) > 95% là tốt. Nếu thấp, tăng opcache.memory_consumption.
Kiểm tra hiệu quả tối ưu
Apache Benchmark (ab)
# Cài đặt
yum install httpd-tools # CentOS/RHEL
apt install apache2-utils # Ubuntu/Debian
# Test basic
ab -n 1000 -c 50 http://yourdomain.com/
# Test với keep-alive
ab -n 1000 -c 50 -k http://yourdomain.com/
# Test POST request
ab -n 500 -c 25 -p post_data.txt -T application/x-www-form-urlencoded http://yourdomain.com/contact/
Đọc kết quả:
Requests per second: 156.89 [#/sec] (mean)
Time per request: 318.62 [ms] (mean)
Time per request: 6.37 [ms] (mean, across all concurrent requests)
Transfer rate: 45.67 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 1 2.1 0 12
Processing: 89 314 89.2 298 523
Waiting: 89 313 89.1 297 522
Total: 89 315 89.3 298 523
Chỉ số quan trọng:
- Requests per second: Cao = tốt (aim for 100+)
- Time per request (mean): Thấp = tốt (< 300ms cho dynamic content)
- Failed requests: Phải = 0
Đo TTFB (Time to First Byte)
# Dùng curl
curl -o /dev/null -s -w "Connect: %{time_connect}sTTFB: %{time_starttransfer}sTotal: %{time_total}s" http://yourdomain.com/
# Test nhiều lần
for i in {1..10}; do
curl -o /dev/null -s -w "%{time_starttransfer}" http://yourdomain.com/
done | awk '{sum+=$1; n++} END {print "Average TTFB: " sum/n "s"}'
TTFB benchmark:
- < 200ms: Excellent
- 200-500ms: Good
- 500ms-1s: Acceptable
- > 1s: Need optimization
So sánh trước/sau tối ưu
Trước tối ưu (mặc định):
Requests per second: 67.45 [#/sec]
Time per request: 741.52 [ms]
TTFB average: 0.68s
Sau tối ưu (Nginx + PHP-FPM + OPcache):
Requests per second: 189.32 [#/sec]
Time per request: 264.15 [ms]
TTFB average: 0.24s
💡 Cải thiện: 2.8x requests/second, TTFB giảm 65%.
VPS AZDIGI – Lựa chọn tối ưu cho hiệu năng
Để đạt được hiệu quả tối ưu với Nginx và PHP-FPM, bạn cần VPS có cấu hình phù hợp. VPS SSD AZDIGI và NVMe VPS và băng thông không giới hạn sẽ phát huy tối đa sức mạnh của web stack này.
Gói VPS 4GB RAM phù hợp cho website 100-300k pageviews/tháng với cấu hình tối ưu như hướng dẫn trên. VPS 8GB xử lý thoải mái website lớn hơn hoặc nhiều site cùng lúc.
Hỗ trợ kỹ thuật 24/7 của AZDIGI cũng giúp bạn triển khai tối ưu nhanh chóng, không mất thời gian troubleshoot.
\Nên chọn pm = dynamic hay pm = static?
Dynamic cho VPS 2-4GB RAM, static cho VPS 8GB+ với traffic cao ổn định. Ondemand chỉ dùng khi RAM dưới 2GB và traffic thấp.
pm.max_children bao nhiêu là phù hợp?
Tính theo công thức: (RAM dành cho PHP) / (50-60MB) = max_children. VPS 4GB thường để 30-40. Monitor ‘ps aux | grep php-fpm’ để điều chỉnh.
OPcache có làm website chậm không?
Không. OPcache chỉ tăng tốc. Nếu thấy chậm, có thể do opcache.memory_consumption quá nhỏ hoặc revalidate_freq quá ngắn (development).
Tối ưu này có áp dụng được cho WordPress không?
Có. WordPress rất hưởng lợi từ OPcache và PHP-FPM tuning. Nên kết hợp thêm Redis object cache và CDN cho hiệu quả tối đa.
Worker connections 2048 có quá cao cho VPS nhỏ không?
Không. Worker connections chỉ là limit tối đa, không tốn RAM khi chưa dùng. VPS 1GB RAM vẫn có thể set 2048 worker_connections an toàn. Chỉ cần theo dõi actual concurrent connections.
Có thể bạn cần xem thêm
- WordPress trên VPS chạy chậm: Hướng dẫn tối ưu toàn diện
- Swap trên VPS: Khi nào cần, cách tạo và tối ưu
- VPS bị chậm do mạng: Cách kiểm tra và khắc phục
- Load Average cao trên Linux Server: Chẩn đoán và xử lý
- VPS đầy ổ cứng: Cách tìm và dọn dẹp dung lượng
- Lỗi 502 Bad Gateway: nguyên nhân và cách khắc phục
Về tác giả
Trần Thắng
Chuyên gia tại AZDIGI với nhiều năm kinh nghiệm trong lĩnh vực web hosting và quản trị hệ thống.