Chuyển đến nội dung chính (Skip to content)
Mục lục bài viết
Nginx

Cấu hình Gzip và Brotli trên NGINX

Cấu hình Gzip và Brotli trên NGINX

Chọn Gzip hoặc Brotli theo module và nội dung, dùng pre-compression cho asset tĩnh, kiểm tra Content-Encoding, Vary và chi phí CPU.

Trước khi bắt đầu. Nén giúp giảm dữ liệu truyền với nội dung phù hợp, đổi lại là chi phí xử lý. Mức nén và tỷ lệ tiết kiệm phụ thuộc dữ liệu; không dùng một tỷ lệ minh họa làm kết quả benchmark.

Sơ đồ kiểm tra gzip brotli nginx
Hai nhánh kiểm tra ban đầu: không thương lượng encoding hoặc có encoding nhưng không nén. Chạm vào hình để mở bản lớn.

1. Vai trò của nén dữ liệu đối với hiệu năng Web và Core Web Vitals

Trong quá trình tối ưu hóa trải nghiệm người dùng, tốc độ tải trang (Page Load Time) là yếu tố quyết định tỷ lệ giữ chân khách hàng và thứ hạng tìm kiếm trên Google. Các chỉ số quan trọng trong bộ tiêu chuẩn Core Web Vitals như LCP (Largest Contentful Paint) và FCP (First Contentful Paint) phụ thuộc trực tiếp vào thời gian trình duyệt tải về các tệp tin HTML, mã kịch bản JavaScript và bảng định kiểu CSS.

Bằng cách kích hoạt cơ chế nén HTTP trên NGINX, bạn có thể giảm dung lượng truyền tải qua mạng từ 65% đến 85% đối với các tài nguyên dạng văn bản, giúp trang web hiển thị nhanh chóng ngay cả trên kết nối di động 3G/4G chập chờn.

Minh họa Accept-Encoding → Chọn Gzip / Brotli → Content-Encoding
Luồng khái niệm: Accept-Encoding → Chọn Gzip / Brotli → Content-Encoding. Chạm vào hình để mở bản lớn.

2. So sánh thuật toán: Gzip vs Brotli

Hiện nay có hai thuật toán nén dữ liệu phổ biến nhất trên môi trường Internet:

  • Gzip (DEFLATE): Tiêu chuẩn công nghiệp truyền thống ra đời từ năm 1992. Ưu điểm là tương thích 100% với mọi trình duyệt, thiết bị di động cũ và thời gian giải nén cực nhanh.
  • Brotli (br): Thuật toán nén thế hệ mới được Google phát triển và mở mã nguồn vào năm 2015. Brotli được thiết kế riêng cho cấu trúc của các ngôn ngữ web với một từ điển tĩnh khổng lồ chứa hơn 13.000 mẫu chuỗi ký tự phổ biến trong HTML/CSS/JS. Nhờ đó, ở cùng mức tiêu thụ CPU, Brotli cho kích thước tệp tin nhỏ hơn Gzip từ 15% đến 25%. Hiện tại, hơn 97% trình duyệt hiện đại trên thế giới đều ưu tiên yêu cầu mã hóa Brotli.

3. Cấu hình nén Gzip chuẩn production

Tạo file cấu hình dùng chung /etc/nginx/conf.d/compression.conf hoặc đặt trực tiếp trong khối http của /etc/nginx/nginx.conf:

# 1. Kích hoạt module Gzip
gzip on;

# 2. Thêm header Vary: Accept-Encoding để các CDN và Proxy cache đúng biến thể nén
gzip_vary on;

# 3. Cho phép nén cả các request được chuyển tiếp qua Proxy
gzip_proxied any;

# 4. Mức độ nén tối ưu (Thang từ 1 đến 9)
# Mức 5-6 là điểm cân bằng vàng giữa kích thước tệp tin và mức chiếm dụng CPU
gzip_comp_level 5;

# 5. Kích thước tối thiểu để bắt đầu nén (1KB)
# Không nén tệp quá nhỏ vì phần tiêu đề nén có thể làm tăng dung lượng
gzip_min_length 1024;

# 6. Danh sách các loại MIME Types được phép nén
gzip_types
    text/plain
    text/css
    text/xml
    text/javascript
    application/javascript
    application/x-javascript
    application/json
    application/xml
    application/xml+rss
    application/wasm
    image/svg+xml
    image/x-icon;

4. Cài đặt và kích hoạt thuật toán nén Brotli

Để sử dụng Brotli, bạn cần cài đặt module NGINX Brotli tương ứng:

Trên Ubuntu / Debian:

sudo apt update
# Tim goi tuong thich voi kho NGINX dang dung truoc khi cai
apt-cache search nginx | grep -i brotli
# Ten goi va cach load_module thay doi theo ban phan phoi.

Bổ sung cấu hình Brotli song song với Gzip trong /etc/nginx/conf.d/compression.conf:

# Kích hoạt module Brotli động (on-the-fly compression)
brotli on;

# Mức độ nén cho dynamic content (khuyến nghị mức 4-5 để tránh tiêu tốn CPU)
brotli_comp_level 4;

# Kích thước tệp tin tối thiểu
brotli_min_length 1024;

# Danh sách MIME Types nén bằng Brotli
brotli_types
    text/plain
    text/css
    text/xml
    text/javascript
    application/javascript
    application/x-javascript
    application/json
    application/xml
    application/xml+rss
    application/wasm
    image/svg+xml
    image/x-icon;

5. Kỹ thuật pre-compression: gzip_static và brotli_static

Một điểm yếu lớn khi nén động theo thời gian thực (Dynamic Compression) là CPU máy chủ phải thực thi giải thuật nén mỗi khi có người dùng truy cập. Đối với các file tĩnh không thay đổi thường xuyên như các bundle Javascript/CSS của React, Vue, Next.js, cách làm này gây lãng phí tài nguyên máy chủ rất lớn.

Giải pháp chuyên nghiệp: Nén sẵn các file tĩnh trong quy trình Build (CI/CD Pipeline) và cấu hình NGINX truyền trực tiếp file nén sẵn với directive gzip_static và brotli_static.

Bước 5.1: Bật tính năng Static pre-compression trong NGINX

# Kiểm tra xem có file .gz hoặc .br trùng tên trên đĩa hay không trước khi nén realtime
gzip_static on;
brotli_static on;

Bước 5.2: Tạo file nén sẵn ở mức tối đa trong quy trình Build

Vì việc nén chỉ diễn ra một lần duy nhất lúc build dự án, bạn có thể sử dụng mức nén cao hơn nếu thời gian build và tài nguyên cho phép; Brotli level 11 hoặc Gzip level 9 có thể làm build chậm đáng kể:

# Sử dụng công cụ brotli và gzip trên Linux để nén toàn bộ assets trong thư mục dist
find /var/www/example.com/html -type f \( -name "*.js" -o -name "*.css" -o -name "*.svg" -o -name "*.json" \) -exec brotli -f -k -q 11 {} \;
find /var/www/example.com/html -type f \( -name "*.js" -o -name "*.css" -o -name "*.svg" -o -name "*.json" \) -exec gzip -f -k -9 {} \;

Khi người dùng gửi request GET /assets/app.js, NGINX sẽ tự động kiểm tra:

  • Nếu client hỗ trợ Brotli và trên đĩa có sẵn app.js.br: NGINX truyền trực tiếp app.js.br kèm header Content-Encoding: br mà tiêu tốn 0% CPU.
  • Nếu client chỉ hỗ trợ Gzip và có app.js.gz: NGINX truyền trực tiếp app.js.gz kèm Content-Encoding: gzip.

6. Các định dạng thường không có lợi khi nén lại

Một sai lầm rất phổ biến là đưa các định dạng hình ảnh và đa phương tiện vào danh sách gzip_types hoặc brotli_types. Bạn tuyệt đối không được nén các định dạng sau:

  • Hình ảnh đã nén sẵn: JPEG, PNG, GIF, WebP, AVIF.
  • Tệp nén lưu trữ: ZIP, GZ, RAR, 7Z, TAR.
  • Tệp âm thanh và video: MP3, MP4, WebM, OGG.
  • Tệp tài liệu đã nén nội bộ: PDF, DOCX, XLSX.

Các định dạng này vốn đã sử dụng các thuật toán nén chuyên dụng đạt tỷ lệ nén tối đa. Nếu cố tình nén tiếp bằng Gzip/Brotli, bạn chỉ làm tiêu hao CPU vô ích và trong nhiều trường hợp dung lượng file còn bị phình to hơn do phần header nén bổ sung.

7. Kiểm tra và xác nhận tỷ lệ nén thực tế

Sau khi nạp lại cấu hình NGINX (sudo nginx -t && sudo systemctl reload nginx), bạn kiểm tra phản hồi từ dòng lệnh:

Kiểm tra nén Brotli:

curl -H "Accept-Encoding: br" -I https://example.com/css/style.css

Kiểm tra xem header phản hồi có xuất hiện dòng: Content-Encoding: br.

Kiểm tra nén Gzip:

curl -H "Accept-Encoding: gzip" -I https://example.com/css/style.css

Kiểm tra xem header phản hồi có xuất hiện dòng: Content-Encoding: gzip.

Với sự kết hợp hoàn hảo giữa nén động và Static Pre-compression, hệ thống của bạn đã đạt hiệu năng truyền tải tối ưu ở tầng mạng. Trong bài học tiếp theo, chúng ta sẽ bước vào cấp độ cao cấp: triển khai Cân bằng tải (Load Balancing) và duy trì phiên làm việc cho các cụm máy chủ High Availability.

Khi đứng sau CDN, phân biệt response từ cache với response ở origin. Kiểm tra Content-Encoding, Vary: Accept-Encoding, kích thước truyền và CPU cùng tải. Brotli là module bổ sung, không mặc định có trong mọi binary NGINX. Với dữ liệu bí mật phản chiếu đầu vào người dùng qua TLS, cần đánh giá nguy cơ side-channel liên quan đến nén trước khi áp dụng.

Nguồn đối chiếu và kiểm tra trước khi áp dụng

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

Tìm hiểu thêm

Xem toàn bộ lộ trình Nginx