
Bài 7: Cấu hình NGINX load balancing và duy trì phiên
Thiết lập upstream, kiểm tra lỗi thụ động và giới hạn retry; phân biệt định tuyến theo IP, cookie và lưu session tập trung trong cụm backend.

Tách tên miền bằng server block, phục vụ website tĩnh, kết nối PHP-FPM và chuyển tiếp đến ứng dụng. Kèm cách kiểm tra chọn đúng virtual host.
Trước khi bắt đầu. Một server block định nghĩa cách NGINX xử lý một nhóm tên miền. Tách file cấu hình giúp dễ bảo trì, nhưng không thay thế cô lập tài khoản, tiến trình hoặc quyền truy cập của ứng dụng.

Trong NGINX, khái niệm Server Block (tương đương với Virtual Host trong Apache) cho phép bạn lưu trữ và vận hành hàng chục tên miền, ứng dụng web hoàn toàn độc lập trên cùng một máy chủ vật lý hoặc VPS duy nhất.
Khi một request HTTP gửi tới máy chủ, NGINX thực hiện phân giải và định tuyến theo thứ tự ưu tiên chặt chẽ:
listen (ví dụ: listen 80; hoặc listen 443;).Host của request và đối chiếu với danh sách tên miền khai báo trong directive server_name. Thứ tự khớp lần lượt là: Tên miền chính xác > Tên miền chứa ký tự đại diện bắt đầu (*.example.com) > Tên miền chứa ký tự đại diện kết thúc (mail.*) > Biểu thức chính quy (Regular Expression).default_server trên cổng tương ứng.
Dưới đây là quy trình chuẩn để thiết lập một website tĩnh (HTML, CSS, JS) cho tên miền static.example.com.
sudo mkdir -p /var/www/static.example.com/html
sudo chown -R www-data:www-data /var/www/static.example.com/html
sudo chmod -R 755 /var/www/static.example.com
Tạo một file kiểm tra đơn giản /var/www/static.example.com/html/index.html:
<!DOCTYPE html>
<html lang="vi">
<head><meta charset="UTF-8"><title>Static Site NGINX</title></head>
<body><h1>Xin chào từ static.example.com!</h1></body>
</html>
Tạo file /etc/nginx/conf.d/static.example.com.conf với nội dung sau:
server {
listen 80;
listen [::]:80;
server_name static.example.com;
root /var/www/static.example.com/html;
index index.html index.htm;
access_log /var/log/nginx/static.example.com.access.log;
error_log /var/log/nginx/static.example.com.error.log warn;
location / {
try_files $uri $uri/ =404;
}
# Cache tài nguyên tĩnh tối đa 30 ngày
location ~* \.(jpg|jpeg|png|gif|ico|css|js|webp|svg|woff2)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
}
}
Khác với Apache sử dụng mod_php nhúng trực tiếp, NGINX không xử lý mã nguồn PHP nội bộ mà đóng vai trò Reverse Proxy chuyển tiếp các file PHP sang trình xử lý FastCGI riêng biệt là PHP-FPM (PHP FastCGI Process Manager).
Kết nối qua UNIX Domain Socket đem lại hiệu năng vượt trội và tiết kiệm tài nguyên mạng hơn so với kết nối TCP Port (127.0.0.1:9000).
Tạo file cấu hình /etc/nginx/conf.d/app.example.com.conf:
server {
listen 80;
listen [::]:80;
server_name app.example.com;
root /var/www/app.example.com/public;
index index.php index.html;
access_log /var/log/nginx/app.example.com.access.log;
error_log /var/log/nginx/app.example.com.error.log warn;
# Chuyển tiếp toàn bộ request qua Front Controller (Laravel/WordPress)
location / {
try_files $uri $uri/ /index.php?$query_string;
}
# Xử lý các file PHP qua PHP-FPM 8.3 UNIX Socket
location ~ \.php$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param HTTP_PROXY ""; # Khắc phục lỗ hổng httpoxy
fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;
fastcgi_busy_buffers_size 256k;
fastcgi_read_timeout 60s;
}
# Chặn truy cập trực tiếp vào các file ẩn và file nhạy cảm
location ~ /\.(?!well-known) {
deny all;
access_log off;
log_not_found off;
}
}
Trong kiến trúc phát triển ứng dụng hiện đại, NGINX thường đứng trước các ứng dụng chạy trên runtime độc lập như Node.js (Next.js/Express), Python (FastAPI/Django) hoặc Go (Gin/Fiber). NGINX tiếp nhận request từ Internet, xử lý mã hóa SSL và chuyển tiếp lưu lượng vào cổng ứng dụng nội bộ.
Tạo file /etc/nginx/conf.d/api.example.com.conf:
upstream nodejs_backend {
server 127.0.0.1:3000;
keepalive 32; # Tái sử dụng kết nối TCP để tối ưu hiệu năng
}
server {
listen 80;
server_name api.example.com;
access_log /var/log/nginx/api.example.com.access.log;
error_log /var/log/nginx/api.example.com.error.log warn;
location / {
proxy_pass http://nodejs_backend;
proxy_http_version 1.1;
# Thiết lập các header quan trọng để ứng dụng backend nhận đúng IP thật
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Hỗ trợ giao thức WebSocket mượt mà
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
}
Khi quản lý hàng chục Server Block, việc lặp đi lặp lại các đoạn cấu hình giống nhau (như cấu hình FastCGI, cấu hình header bảo mật hoặc SSL) sẽ khiến hệ thống khó bảo trì. Giải pháp là gom các đoạn cấu hình dùng chung vào thư mục /etc/nginx/snippets/.
Ví dụ tạo file /etc/nginx/snippets/fastcgi-php.conf:
fastcgi_split_path_info ^(.+\.php)(/.+)$;
try_files $fastcgi_script_name =404;
set $path_info $fastcgi_path_info;
fastcgi_param PATH_INFO $path_info;
fastcgi_index index.php;
try_files $uri =404;
include fastcgi_params;
Trong các file Virtual Host, bạn chỉ cần một dòng duy nhất: include snippets/fastcgi-php.conf; để áp dụng trọn vẹn cấu hình.
Mỗi khi tạo mới hoặc sửa đổi bất kỳ file cấu hình nào trong /etc/nginx/conf.d/, luôn thực thi quy trình kiểm tra an toàn:
# 1. Kiem tra tinh hop le cua toan bo cu phap
sudo nginx -t
# 2. Neu syntax is ok, tien hanh nap lai cau hinh
sudo systemctl reload nginx
Với phương pháp này, bạn đã thiết lập thành công nền tảng Virtual Host linh hoạt, sẵn sàng phục vụ website tĩnh, ứng dụng PHP hoặc hệ thống Microservices backend. Ở bài tiếp theo, chúng ta sẽ mã hóa toàn bộ lưu lượng web bằng chứng chỉ bảo mật SSL/TLS miễn phí từ Let's Encrypt.
Socket /run/php/php8.3-fpm.sock là ví dụ cho cách bố trí thường gặp trên Ubuntu; kiểm tra pool PHP-FPM, phiên bản, quyền truy cập và SELinux của máy thực tế. Không dùng đường dẫn này cho Rocky Linux nếu pool đang nghe socket khác. Mẫu WebSocket cần phục vụ đúng endpoint; không ép Connection: upgrade cho mọi request nếu ứng dụng không cần. Với 502, xem error log và thử kết nối trực tiếp đến upstream trước khi tăng timeout.
Các địa chỉ example.com, IP riêng và đường dẫn trong ví dụ cần thay theo môi trường thực tế. Các sơ đồ trong bài là minh họa khái niệm, không phải bằng chứng thử nghiệm trên hệ thống của bạn.
Trước khi áp dụng: sao lưu file cấu hình bị đổi, chạy sudo nginx -t, chỉ reload khi kiểm tra thành công, rồi xác nhận endpoint, error log và chức năng ứng dụng. Nếu lỗi xuất hiện, phục hồi file đã sao lưu, kiểm tra cú pháp và reload lại; không xóa hàng loạt cấu hình để thử.

Thiết lập upstream, kiểm tra lỗi thụ động và giới hạn retry; phân biệt định tuyến theo IP, cookie và lưu session tập trung trong cụm backend.

Dựng máy chủ mới, kiểm tra cấu hình và SELinux, thử lưu lượng trước cutover; chuẩn bị rollback khi chuyển NGINX từ CentOS Linux đã hết hỗ trợ.

Định tuyến dịch vụ gRPC qua NGINX, phân biệt kết nối TLS đến upstream, cấu hình timeout cho streaming và kiểm tra bằng grpcurl.

Kiểm tra module, thư viện TLS và cổng UDP 443 trước khi bật HTTP/3; cấu hình HTTP/2 và xác nhận giao thức thực tế từ phía máy khách.