Khắc phục lỗi Nginx (24: Too many open files) khi kết nối Upstream

intermediate Nginx2026-04-12| Linux (Ubuntu, Debian, CentOS, RHEL), Nginx 1.10+

Error Message

socket() failed (24: Too many open files) while connecting to upstream
#nginx#linux-tuning#devops#server-optimization

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ì.

Những lưu ý quan trọng- Giới hạn mặc định là lưới an toàn: Các giới hạn tiêu chuẩn của Linux ngăn chặn các tiến trình mất kiểm soát làm hỏng hệ thống, nhưng chúng bóp nghẹt các máy chủ web có lưu lượng truy cập cao.- Ghi đè Systemd là rất quan trọng: Trên các bản phân phối hiện đại, LimitNOFILE trong service unit là cài đặt quan trọng nhất.- Theo dõi việc sử dụng FD: Sử dụng lệnh lsof -p [PID] | wc -l trong giờ cao điểm để xem Nginx thực sự đang sử dụng bao nhiêu descriptor.- Mở rộng cẩn thận: Mặc dù 65.535 là điểm bắt đầu an toàn, nhưng các giới hạn cực cao có thể tiêu tốn nhiều bộ nhớ kernel hơn.

Related Error Notes