planets-top
Published on

Tối ưu hóa cấu hình Nginx

Authors

Bài viết tìm hiểu về cấu trúc và một số khái niệm trong tệp tin cấu hình mặc định của Nginx. Bên cạnh đó bài viết cũng sẽ đưa ra một số bước cần thiết giúp bạn sử dụng config file của Nginx một cách hiệu quả hơn.

Cấu trúc và cách sử dụng tập tin cấu hình

Cấu trúc

  • Tất cả file cấu hình của nginx nằm trong thư mục – /etc/nginx
  • Document root directory – /usr/share/nginx/html
  • Nginx bao gồm các module được điều khiển bởi các directive trong file cấu hình.

“Directive” được định nghĩa như 1 instruction (chỉ dẫn) hay direct. Directives được chia thành các directive đơn giản và các block directive.

Cấu trúc của 1 directive đơn giản gồm tên và tham số được phân tách bởi dấu cách và kết thúc bằng dấu chấm phẩy (;). Ví dụ về 1 directive đơn giản:

worker_processes 1;

Một block directive có cấu trúc tương tự như một directive đơn giản nhưng thay vì sử dụng dấu ; nó sẽ sử dụng cặp dấu để bắt đầu và kết thúc 1 block directive. Một config file điển hình của nginx có thể được minh họa như hình dưới.

nginx

Một main context sẽ bao gồm nhiều directive đơn giản, nhiều context(ví dụ: context A, context B) chứa các block directive.

Cách sử dụng config file hợp lý và hiệu quả

  • Tạo 1 file cấu hình riêng cho mỗi tên miền sẽ giúp server dễ quản lý và hiệu quả hơn.

  • NGINX không có Virtual host, thay vào đó là Server Blocks sử dụng server_name và nghe các chỉ thị để liên kết với các tcp sockets. Tất cả các file server block phải có định dạng là .conf và được lưu trong thư mục /etc/nginx/conf.d hoặc /etx/nginx/conf.

  • Nếu bạn có 1 domain là mydomain.com thì bạn nên đặt tên file cấu hình là mydomain.com.cnf.

  • Các file nhật ký Nginx (access.log và error.log) được đặt trong thư mục /var/log/nginx/. N��n có một tệp nhật ký access và error khác nhau cho mỗi server block.

  • Bạn có thể đặt document root directory của tên miền của bạn đến bất kỳ vị trí nào bạn muốn. Một số vị trí thường được dùng cho webroot bao gồm:

/home/<user_name>/<site_name>
/var/www/<site_name>
/var/www/html/<site_name>
/opt/<site_name>
/usr/share/nginx/html

Các thao tác cần thực hiện trước và sau khi chỉnh sửa config file

  • Trước khi thay đổi cấu hình sao lưu lại file cấu hình:
cp /etc/nginx/conf/nginx.conf /etc/nginx/conf/nginx.conf.backup
  • Sau khi thực hiện thay đổi cấu hình, restart lại service:
systemctl restart nginx

Tìm hiểu chi tiết về config file

Core Contexts

Đây là nhóm đầu tiên của contexts, được nginx sử dụng để tạo ra 1 cây phân cấp và tách biệt các cấu hình giữa các block. Trong đây cũng bao gồm các cấu hình chính của nginx.

Main Context

Cũng có thể coi là global context. Đây là context chung nhất bao gồm tất cả các directive đơn giản, block directive và các context khác.

#user  nobody;
worker_processes  auto;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;

File bắt đầu cùng với 4 directives: user, worker_processes, error_log, và pid. Chúng nằm ngoài bất kỳ block hay context cụ thể nào, do đó chúng nằm trong main context. Các event và http block là khu vực cho các directives bổ sung, do đó chúng cũng nằm trong main context.

Giải thích cụ thể:

  • user: Định nghĩa cho biết người dùng hệ thống Linux nào sẽ có quyền chạy các máy chủ Nginx. Có những trường hợp sử dụng nhất định mà được hưởng lợi từ việc thay đổi người dùng. Ví dụ, bạn chạy hai máy chủ web cùng một lúc, hoặc cần người sử dụng của một chương trình khác để có thể kiểm soát Nginx.

  • worker_process: có giá trị mặc định là 1. Nó định nghĩa số lượng worker process Nginx sử dụng. Số lượng worker process nên được set bằng giá trị với số core của CPU. Ví dụ với các web server hay sử dụng về SSL, gzip thì ta nên đặt chỉ số của worker_processes này lên cao hơn. Nếu website của bạn có số lượng các tệp tin tĩnh nhiều, và dung lượng của chúng lớn hơn bộ nhớ RAM thì việc tăng worker_processes sẽ tối ưu băng thông đĩa của hệ thống. Để xác định số cores của CPU của hệ thống ta có thể thực hiện lệnh:

    cat /proc/cpuinfo | grep processor

  • access_log & error_log: những file mà Nginx sẽ sử dụng để log lại toàn bộ error và access request. Phần log này thường được sử dụng để debug.

  • pid: Xác định nơi Nginx sẽ ghi lại master process ID, hoặc PID. PID được sử dụng bởi hệ điều hành để theo dõi và gửi tín hiệu đến quá trình Nginx. Bạn có thể xác định thông tin về PID (master process và worker process) của nginx bằng câu lệnh:

    ps -ax | grep nginx

  • worker_connections: cho biết số lượng connection mà mỗi worker_process có thể xử lý. Mặc định, số lượng connection này được thiết lập là 1024. Để xem về mức giới hạn sử dụng của hệ thống bạn có thể dùng lệnh:

    ulimit -n

Con số thiết lập của worker_connections nên nhỏ hơn hoặc bằng giới hạn này!

max clients = worker_connections * worker_processes

Events Context

  events {
  worker_connections  1024;
  }

NGINX sử dụng mô hình xử lý kết nối dựa trên sự kiện (event) nên các directive được định nghĩa trong context này sẽ ảnh hưởng đến connection processing được chỉ định. Ví dụ ở trên là cấu hình số worker connection tối đa mà mỗi worker process có thể xử lý được.

Thiết lập worker_connections quá cao mà không tối ưu hệ điều hành có thể làm hệ thống quá tải.

HTTP Context

Khi cấu hình Nginx như một web server hoặc reverse proxy, http context sẽ giữ phần lớn cấu hình. Context này sẽ chứa tất cả các directive và những context (block directive) cần thiết khác để xác định cách chương trình sẽ xử lý các kết nối HTTPHTTPS.

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;

    gzip  on;
}

Giải thích một số directive:

  • include: Chỉ thị include (include /etc/nginx/mime.types) của nginx có vai trò trong việc thêm nội dung từ một file khác vào trong cấu hình nginx. Điều này có nghĩa là bất cứ điều gì được viết trong tập tin mime.types sẽ được hiểu là nó được viết bên trong khối http {}. Điều này cho phép bạn bao gồm một số lượng dài của các chỉ thị trong khối http {} mà không gây lộn xộn lên các tập tin cấu hình chính. Và nó giúp tránh quá nhiều dòng mã cho mục đích dễ đọc. Bạn luôn có thể bao gồm (include) tất cả các tập tin trong một thư mục nhất định với các chỉ thị: include /etc/nginx/conf/*; Bạn cũng có thể bao gồm tất cả file theo một định dạng nào đó, như ví dụ sau: include /etc/nginx/conf/*.conf; –> Nó sẽ bao gồm các tập tin có đuôi .conf.
  • "gzip:" Chỉ thị gzip sẽ giúp nén các dữ liệu trước khi chuyển chúng tới Client, hạn chế số lượng băng thông sử dụng và tăng tốc độ dịch chuyển dữ liệu. Điều này tương đương với mod_deflate của Apache. Một số chỉ thị sau đây bạn có thể thêm vào để tăng hiệu quả của gzip, nhớ phải uncommnet mới có hiệu quả.
# gzip_vary on;
# gzip_proxied any;
# gzip_comp_level 6;
# gzip_buffers 16 8k;
# gzip_http_version 1.1;
# gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
  • sendfile on: Kích hoạt tính năng sendfile để gửi file trực tiếp từ đĩa tới socket.
  • keepalive_timeout: Thời gian giữ kết nối mở giữa client và server trước khi đóng.

Server Context

Được khai báo trong http context. Đây cũng là một ví dụ về context lồng nhau được đặt trong ngoặc. Đây cũng là context đầu tiên cho phép khai báo nhiều lần.

    listen       443 ssl;
    server_name  example.com;

    ssl_certificate      /path/to/cert.pem;
    ssl_certificate_key  /path/to/cert.key;

    location ~ \.php$ {
        root   html;
        index  index.html index.htm;
        root           html;
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        include        fastcgi_params;
    }

NGINX hỗ trợ cấu hình HTTPS để bảo vệ các kết nối HTTP.

Dựa vào yêu cầu từ phía client, Nginx sẽ sử dụng thuật toán lựa chọn để quyết định server context nào được sử dụng. Các directive được sử dụng để quyết định server context nào được sử dụng là:

  • listen: sự kết hợp của IP/port mà server block này được thiết kế để đáp ứng. Nếu một yêu cầu từ phía client phù hợp với giá trị này, block này có thể được lựa chọn để xử lý kết nối.
  • server_name: Nếu có nhiều server block đáp ứng được yêu cầu của listen directive, nginx sau đó sẽ tiến hành phân tích cú pháp tiêu đề “Host” của yêu cầu và lựa chọn block phù hợp.

Location Context

  • Được đặt trong server context.

  • Sau khi đã chọn được server context nào sẽ ti���p nhận request này thì nginx sẽ tiếp tục phân tích URI của request để tìm ra hướng xử lí của request dựa vào các location context có syntax như sau:

location optional_modifier location_match {
. . .
}
  • (none): Nếu không khai báo gì thì NGINX sẽ hiểu là tất cả các request có URI bắt đầu bằng phần location_match sẽ được chuyển cho location block này xử lí.
  • =: Khai báo này chỉ ra rằng URI phải có chính xác giống như location_match (giống như so sánh string bình thường).
  • ~: Sử dụng regular expression cho các URI.
  • ~*: Sử dụng regular expression cho các URI cho phép pass cả chữ hoa và chữ thường.

Khi nào thì location block sẽ nhảy vào khối block khác?

Thông thường khi mà location block được dùng để phục vụ một request nào đó thì action sẽ hoàn toàn nằm trong context của nó (bên trong dấu {}). Và nó sẽ chỉ nhảy sang các block khác hay chuyển hướng xử lí request khi có yêu cầu từ chính bên trong context của nó. Một vài directive có thể redirective request.

Ví dụ:

- index
- try_files
- rewrite
- error_page

index directive

index direct nằm bên trong location luôn được nginx trỏ tới đầu tiên khi xử lí điều hướng request. Định nghĩa trang mặc định mà Nginx sẽ phục vụ nếu không có tên tập tin được chỉ rõ trong yêu cầu (nói cách khác, trang chỉ mục). Chúng ta có thể chỉ rõ nhiều tên tập tin và tập tin đầu tiên được tìm thấy sẽ được sử dụng. Nếu không có tập tin cụ thể nào được tìm thấy, Nginx sẽ hoặc là cố gắng phát sinh 1 chỉ mục tự động của các tập tin

location = / {
    index index.html;
}

index directive Cố gắng phục vụ các tập tin được chỉ rõ (các tham số từ 1 đến N-1 trong chỉ thị), nếu không có tập tin nào tồn tại, nhảy đến khối location được khai báo (tham số cuối cùng trong chỉ thị) hoặc phục vụ 1 URI được chỉ định.

location = / {
   try_files $uri $uri.html $uri/ /fallback/index.html;
}

index directive Khác với Apache, Nginx không sử dụng file .htaccess nên khi bạn cần rewrite url sẽ phải convert qua rule của Nginx. Trong bài viết này, mình sẽ đưa ra một số ví dụ các rule của Nginx sử dụng để rewrite url, redirect và một số cấu hình cần thiết khác.

location /download/ {
    rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 break;
    rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra  break;
    return  403;
}

error_page directive Chỉ thị khi không tìm thấy file tham chiếu.

location / {
    error_page 404 = @fallback;
}

location @fallback {
    proxy_pass http://backend;
}

Hy vọng rằng qua bài viết này, bạn đã có thể hiểu rõ hơn về các khái niệm và cách thiết lập NGINX cho các mục đích khác nhau.

Một số tips tối ưu hiệu suất Nginx

  1. Bật nén Gzip cho các loại file phù hợp
  2. Sử dụng cache cho static content
  3. Tối ưu số lượng worker processes và worker connections
  4. Sử dụng keepalive connections
  5. Bật HTTP/2 nếu có thể
  6. Cấu hình microcache cho các nội dung động

Monitoring và Debug

Để theo dõi hiệu suất của Nginx, bạn có thể:

  1. Sử dụng module ngx_http_stub_status_module
  2. Theo dõi access.log và error.log
  3. Sử dụng các công cụ monitoring như Nginx Amplify
  4. Kiểm tra tải hệ thống với top hoặc htop