❤️ 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 cache
  • max_accelerated_files=10000: Cache tối đa 10000 files PHP
  • revalidate_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 AZDIGINVMe VPSbă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.

Chia sẻ:
Bài viết đã được kiểm duyệt bởi AZDIGI Team

Về tác giả

Trần Thắng

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.

Hơn 10 năm phục vụ 80.000+ khách hàng

Bắt đầu dự án web của bạn với AZDIGI