Vấn đề: Chạm ngưỡng giới hạn File DescriptorCác máy chủ Nginx bận rộn thường gặp phải rào cản khi đột ngột ngừng chấp nhận lưu lượng hoặc không thể giao tiếp với các dịch vụ backend như Node.js hoặc PHP-FPM. Nếu bạn kiểm tra nhật ký (log) tại /var/log/nginx/error.log và thấy lỗi nghiêm trọng (24: Too many open files), nghĩa là máy chủ của bạn đã cạn kiệt tài nguyên. Điều này thường xảy ra vì Linux coi hầu hết mọi thứ—từ socket mạng đến các tệp nhật ký—là một File Descriptor (FD).
Theo mặc định, nhiều bản phân phối Linux giới hạn một tiến trình đơn lẻ ở mức 1.024 tệp mở. Mặc dù mức này an toàn cho máy tính cá nhân, nhưng một máy chủ web hiệu suất cao xử lý 5.000 người dùng đồng thời sẽ chạm giới hạn này chỉ trong vài mili giây. Để khắc phục, chúng ta cần nâng mức trần này trên toàn bộ hệ điều hành (OS), trình quản lý dịch vụ và bản thân Nginx.
Bước 1: Kiểm tra các giới hạn hiện tạiBắt đầu bằng cách xác định giới hạn thực tế đang áp dụng cho các tiến trình worker của Nginx đang chạy. Bạn có thể tìm Process ID (PID) và kiểm tra các giới hạn của nó trực tiếp thông qua hệ thống tệp /proc.
# Xác định PID của một Nginx worker đang hoạt động
ps aux | grep nginx
# Kiểm tra các giới hạn cho PID đó (ví dụ: 1234)
cat /proc/1234/limits | grep "Max open files"
Nếu bạn thấy "Soft Limit" là 1024, bạn đã tìm ra điểm nghẽn. Con số này quá thấp đối với các hệ thống production hiện đại.
Bước 2: Điều chỉnh giới hạn ở cấp độ hệ điều hànhHệ điều hành cần được cấp phép để cung cấp nhiều descriptor hơn cho người dùng Nginx. Mở tệp /etc/security/limits.conf để xác định các ranh giới toàn cục này.
sudo nano /etc/security/limits.conf
Thêm các dòng sau vào cuối tệp. Hãy đảm bảo sử dụng đúng người dùng (user) mà dịch vụ Nginx của bạn đang chạy (thường là www-data hoặc nginx):
nginx soft nofile 65535
nginx hard nofile 65535
Việc này đặt giới hạn thành 65.535, một giá trị tiêu chuẩn cho các hệ thống hiệu suất cao. Tuy nhiên, trên các hệ thống hiện đại, chỉ tệp này thôi là chưa đủ.
Bước 3: Cập nhật cấu hình SystemdCác phiên bản Linux hiện đại (Ubuntu 18.04+, CentOS 7+) sử dụng Systemd, công cụ này thường bỏ qua limits.conf đối với các dịch vụ chạy ngầm. Bạn phải chỉ định rõ ràng cho Systemd cho phép giới hạn cao hơn cho đơn vị (unit) Nginx.
Tạo một tệp ghi đè (override) để giữ cho các thay đổi của bạn an toàn khi cập nhật gói phần mềm:
sudo mkdir -p /etc/systemd/system/nginx.service.d/
sudo nano /etc/systemd/system/nginx.service.d/override.conf
Dán cấu hình sau vào:
[Service]
LimitNOFILE=65535
Sau khi lưu, hãy tải lại daemon Systemd để nó nhận diện các hướng dẫn mới:
sudo systemctl daemon-reload
Bước 4: Cấu hình giới hạn Worker của NginxNgay cả khi hệ điều hành cho phép 65.000 tệp, Nginx sẽ không sử dụng chúng trừ khi bạn yêu cầu. Bạn cần đồng bộ các cài đặt nội bộ của Nginx với giới hạn hệ thống mới của mình.
Mở /etc/nginx/nginx.conf và thêm chỉ thị worker_rlimit_nofile ở cấp cao nhất:
user nginx;
worker_processes auto;
worker_rlimit_nofile 65535; # Khớp với giới hạn của hệ điều hành
events {
worker_connections 16384; # Giữ giá trị này thấp hơn đáng kể so với rlimit_nofile
}
http {
...
}
Quy tắc 2:1: Luôn đặt worker_rlimit_nofile ít nhất gấp đôi worker_connections của bạn. Mỗi yêu cầu được proxy sử dụng ít nhất hai file descriptor: một cho kết nối máy khách và một cho kết nối đến backend upstream của bạn.
Bước 5: Áp dụng và Kiểm traKiểm tra cấu hình để tìm lỗi cú pháp trước khi khởi động lại dịch vụ:
sudo nginx -t
Nếu kiểm tra thành công, hãy khởi động lại Nginx để áp dụng tất cả các thay đổi:
sudo systemctl restart nginx
Cuối cùng, xác nhận các giới hạn mới đã có hiệu lực cho các tiến trình mới. Chạy lệnh này để kiểm tra PID worker mới nhất:
NEW_PID=$(pgrep -n nginx)
cat /proc/$NEW_PID/limits | grep "Max open files"
Bây giờ bạn sẽ thấy giới hạn được hiển thị là 65535. Máy chủ của bạn hiện có thể xử lý hàng chục nghìn kết nối đồng thời mà không gặp khó khăn gì.

