Nâng cấp Nginx: Tối ưu hóa để đối phó với tải lớn

1. Tận dụng tối đa tài nguyên CPU: Worker Processes và Connections
Đây là những thiết lập cơ bản nhưng lại cực kỳ quan trọng. Nginx hoạt động hiệu quả nhất khi số lượng worker processes tương ứng với số lõi CPU của máy chủ.
# /etc/nginx/nginx.conf hoặc file cấu hình chính của bạn
worker_processes auto; # Nginx sẽ tự động phát hiện và sử dụng tất cả các lõi CPU có sẵn.
# Hoặc bạn có thể đặt một số cụ thể, ví dụ: worker_processes 4;
events {
worker_connections 2048; # Số lượng kết nối tối đa mà mỗi worker process có thể xử lý.
# Giá trị này phụ thuộc vào tài nguyên hệ thống (RAM, File Descriptors).
# Bạn có thể tăng lên 4096 hoặc cao hơn tùy thuộc vào máy chủ.
multi_accept on; # Cho phép mỗi worker chấp nhận nhiều kết nối mới cùng lúc.
use epoll; # (Linux) Sử dụng phương thức xử lý sự kiện hiệu quả nhất.
# Trên FreeBSD/macOS, có thể là kqueue.
}
worker_processes auto;
: Đảm bảo Nginx tận dụng toàn bộ sức mạnh xử lý đa lõi của CPU.worker_connections
: Đây là giới hạn quan trọng. Tổng số kết nối mà Nginx có thể xử lý đồng thời làworker_processes * worker_connections
. Hãy chắc chắn rằng giá trị này đủ lớn để đáp ứng nhu cầu của bạn, nhưng cũng đừng đặt quá cao so với tài nguyên hệ thống thực tế.
2. Giảm thiểu chờ đợi: Tối ưu hóa Timeouts
Các kết nối chờ đợi không cần thiết sẽ chiếm giữ tài nguyên. Giảm thời gian timeout giúp Nginx nhanh chóng giải phóng tài nguyên cho các kết nối mới.
# Trong khối http {} của file cấu hình chính
http {
# ... các cấu hình khác ...
keepalive_timeout 30; # Giữ kết nối HTTP persistent trong 30 giây.
# Nếu trang web của bạn có nhiều request ngắn, hãy giảm xuống 15-30s.
send_timeout 60; # Timeout khi Nginx gửi phản hồi cho client.
client_header_timeout 60; # Timeout khi Nginx đọc header từ client.
client_body_timeout 60; # Timeout khi Nginx đọc body từ client.
}
keepalive_timeout
: Giảm giá trị này khi có lượng truy cập lớn sẽ giúp Nginx nhanh chóng đóng các kết nối không hoạt động, giải phóng tài nguyên.Các timeout khác như
send_timeout
,client_header_timeout
,client_body_timeout
cũng nên được điều chỉnh để ngăn chặn các kết nối "treo" làm tiêu tốn tài nguyên.
3. Quản lý bộ đệm và kích thước Body: Tránh tràn bộ nhớ
Các request với kích thước lớn hoặc không được quản lý bộ đệm hiệu quả có thể gây lãng phí bộ nhớ và I/O đĩa.
# Trong khối http {}
http {
# ...
client_max_body_size 50M; # Kích thước body request tối đa (ví dụ: upload file).
# Đặt giá trị phù hợp với nhu cầu ứng dụng của bạn.
client_body_buffer_size 128k; # Kích thước buffer cho body request nhỏ.
# Nếu body lớn hơn, Nginx sẽ ghi vào file tạm.
client_header_buffer_size 1k; # Kích thước buffer cho header request.
large_client_header_buffers 4 8k; # Số lượng và kích thước các buffer cho header lớn.
# Nếu Nginx hoạt động như Proxy (ví dụ: với PHP-FPM, Node.js)
proxy_buffer_size 4k;
proxy_buffers 8 16k;
proxy_busy_buffers_size 32k;
proxy_temp_file_write_size 32k;
}
client_max_body_size
: Giới hạn kích thước tải lên là cần thiết để bảo vệ hệ thống khỏi các cuộc tấn công DoS hoặc việc tải lên quá lớn.Các thiết lập
*_buffer_size
vàproxy_buffers
giúp Nginx xử lý dữ liệu trong bộ nhớ hiệu quả hơn, giảm thiểu việc ghi/đọc từ đĩa.
4. Nén dữ liệu: Bật Gzip Compression
Nén dữ liệu truyền tải không chỉ giúp tăng tốc độ tải trang mà còn giảm đáng kể băng thông, đặc biệt quan trọng khi đối mặt với tải lớn.
# Trong khối http {}
http {
# ...
gzip on;
gzip_vary on; # Thêm header Vary: Accept-Encoding
gzip_proxied any; # Kích hoạt nén ngay cả khi qua proxy
gzip_comp_level 5; # Mức độ nén (1-9, 5 là mức cân bằng tốt giữa CPU và tỷ lệ nén).
gzip_buffers 16 8k; # Kích thước bộ đệm nén.
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml;
gzip_disable "MSIE [1-6]\."; # Tắt nén cho các trình duyệt IE cũ có vấn đề.
}
gzip on;
: Kích hoạt nén Gzip.gzip_comp_level
: Hãy thử nghiệm để tìm ra mức tối ưu cho hệ thống của bạn; mức 5-6 thường là lựa chọn tốt.gzip_types
: Chỉ nén các loại nội dung cần thiết để tránh lãng phí CPU cho việc nén các file đã được nén sẵn (ví dụ: ảnh JPEG).
5. Tăng tốc nội dung tĩnh: Cấu hình Cache
Nginx cực kỳ mạnh mẽ trong việc phục vụ các file tĩnh (ảnh, CSS, JS). Việc cấu hình cache đúng cách sẽ giảm tải cho máy chủ backend và tăng tốc độ tải trang đáng kể.
# Trong khối server {} hoặc location {} cho các file tĩnh
server {
# ...
location ~* \.(jpg|jpeg|gif|png|ico|css|js|html|webp|woff2|ttf|svg)$ {
expires 30d; # Cache trên trình duyệt client trong 30 ngày.
add_header Cache-Control "public, no-transform"; # Chỉ định cache công khai.
# Tùy chọn: Bật open_file_cache để lưu thông tin file trong bộ nhớ
# open_file_cache max=1000 inactive=20s;
# open_file_cache_valid 30s;
# open_file_cache_min_uses 2;
# open_file_cache_errors on;
}
}
expires
: Hướng dẫn trình duyệt client lưu trữ các file tĩnh, giúp các lần truy cập sau không cần tải lại từ server.open_file_cache
: Nếu bạn có rất nhiều file tĩnh được truy cập thường xuyên, việc bậtopen_file_cache
sẽ giúp Nginx tìm và phục vụ chúng nhanh hơn bằng cách lưu trữ thông tin về file trong RAM.
6. Phân phối tải: Load Balancing với Nginx (Nếu có)
Nếu bạn có nhiều máy chủ ứng dụng (backend), Nginx đóng vai trò là một Load Balancer hiệu quả, giúp phân phối lưu lượng truy cập đều giữa các server.
# Trong khối http {}
http {
upstream my_backend_servers {
server backend1.example.com:8080 weight=5; # Server này sẽ nhận 5 lần request so với server khác
server backend2.example.com:8080;
server backend3.example.com:8080 backup; # Server dự phòng
server backend4.example.com:8080 max_fails=3 fail_timeout=30s; # Kiểm tra sức khỏe của server
# Phương pháp cân bằng tải:
# least_conn; # Ưu tiên server có ít kết nối nhất. Rất tốt cho các request có thời gian xử lý khác nhau.
# ip_hash; # Đảm bảo client luôn được chuyển đến cùng một server (hữu ích cho session sticky).
}
server {
listen 80;
server_name yourdomain.com;
location / {
proxy_pass http://my_backend_servers;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
}
upstream
: Định nghĩa nhóm các server backend của bạn.least_conn
: Thường là thuật toán cân bằng tải tốt nhất cho hiệu suất, vì nó hướng các request mới tới server đang ít bận rộn nhất.weight
,max_fails
,fail_timeout
: Các tùy chọn này cho phép bạn kiểm soát cách Nginx phân phối tải và cách nó xử lý các server bị lỗi.
7. Bảo vệ hệ thống: Giới hạn Tỷ lệ Request (Rate Limiting)
Để bảo vệ máy chủ khỏi các cuộc tấn công DoS, brute-force, hoặc lạm dụng API, việc giới hạn số lượng request từ một IP là cực kỳ cần thiết.
# Trong khối http {}
http {
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=5r/s; # Giới hạn 5 request/giây từ mỗi IP.
# 10MB đủ cho khoảng 160.000 địa chỉ IP.
server {
listen 80;
server_name yourdomain.com;
location /api/login {
limit_req zone=mylimit burst=10 nodelay; # Áp dụng giới hạn. Cho phép "burst" 10 request.
# nodelay: request vượt quá burst sẽ bị từ chối ngay lập tức (503).
# Nếu không có nodelay, Nginx sẽ trì hoãn request.
# ...
}
}
}
limit_req_zone
: Định nghĩa vùng nhớ và tỷ lệ giới hạn.$binary_remote_addr
được sử dụng để theo dõi từng IP client.limit_req
: Áp dụng giới hạn đã định nghĩa cho cáclocation
cụ thể.burst
cho phép một lượng nhỏ request vượt quá giới hạn trong thời gian ngắn mà không bị từ chối ngay.
8. Tăng cường khả năng xử lý: Tăng File Descriptors (FDs)
Mỗi kết nối, mỗi file được mở đều yêu cầu một File Descriptor (FD). Khi tải lớn, Nginx có thể nhanh chóng chạm tới giới hạn FDs của hệ điều hành.
Trong Nginx config (
nginx.conf
, ngoài các khốihttp
,events
): Nginxworker_rlimit_nofile 65535; # Đặt giới hạn FDs cho worker processes của Nginx.
Trong hệ điều hành (Linux): Bạn cần tăng giới hạn cho user mà Nginx chạy trong
/etc/security/limits.conf
và/hoặc tăng giới hạn toàn hệ thống trong/etc/sysctl.conf
.Thêm vào
/etc/security/limits.conf
:nginx_user_name soft nofile 65535 nginx_user_name hard nofile 65535
(Thay
nginx_user_name
bằng user mà Nginx chạy, thường lànginx
hoặcwww-data
).Thêm vào
/etc/sysctl.conf
:fs.file-max = 200000
Sau đó chạy
sudo sysctl -p
để áp dụng các thay đổi kernel.
9. Điều chỉnh Kernel (Linux): Tối ưu hóa mạng
Một số điều chỉnh ở cấp độ kernel có thể cải thiện đáng kể hiệu suất mạng của máy chủ, hỗ trợ Nginx xử lý nhiều kết nối hơn.
Thêm vào
/etc/sysctl.conf
và chạysudo sysctl -p
:net.core.somaxconn = 65535 # Tăng hàng đợi kết nối TCP chưa được chấp nhận. net.core.netdev_max_backlog = 65535 # Tăng hàng đợi gói tin đến. net.core.rmem_max = 16777216 # Kích thước buffer nhận tối đa. net.core.wmem_max = 16777216 # Kích thước buffer gửi tối đa. net.ipv4.tcp_max_syn_backlog = 65535 # Hàng đợi các yêu cầu SYN. net.ipv4.tcp_tw_reuse = 1 # Cho phép tái sử dụng các kết nối trong trạng thái TIME_WAIT. net.ipv4.tcp_fin_timeout = 15 # Thời gian chờ kết nối đóng. net.ipv4.tcp_keepalive_time = 600 # Thời gian kiểm tra keepalive.
Những điều chỉnh này giúp kernel quản lý tốt hơn các kết nối mạng, giảm thiểu tình trạng "treo" hoặc bị từ chối do thiếu tài nguyên.
Lời kết và những lưu ý quan trọng
Việc tối ưu hóa Nginx là một quá trình liên tục. Sau mỗi thay đổi, hãy nhớ:
Kiểm tra cú pháp: Luôn chạy
sudo nginx -t
để đảm bảo không có lỗi cú pháp.Khởi động lại/Reload Nginx: Sử dụng
sudo systemctl reload nginx
hoặcsudo service nginx reload
để Nginx tải lại cấu hình mà không làm gián đoạn các kết nối hiện có.Theo dõi hiệu suất: Sử dụng các công cụ giám sát (như
htop
,top
,netstat
, hoặc các hệ thống chuyên nghiệp như Prometheus/Grafana) để theo dõi CPU, RAM, I/O, và số lượng kết nối. Dữ liệu này sẽ cho bạn biết những thay đổi nào thực sự hiệu quả.Hiểu rõ ứng dụng backend: Nginx là một tấm khiên vững chắc, nhưng nếu ứng dụng backend của bạn chưa được tối ưu hóa, nó vẫn có thể là nút thắt cổ chai. Hãy đảm bảo cả Nginx và ứng dụng của bạn đều hoạt động hiệu quả.
Subscribe to my newsletter
Read articles from Kilo directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
