一、概述
1.1 背景介紹
說起Gzip壓縮,可能很多人覺得這是個老生常談的話題。但我在這幾年的運維工作中發現,真正把Gzip配置到位的網站其實不多。去年幫一個客戶做性能優化,他們的網站日均帶寬消耗在2TB左右,一看Nginx配置,Gzip居然只開了默認的gzip on,壓縮級別是1,很多該壓的文件類型都沒加上。調整完配置后,帶寬直接降到800GB,每個月省下來的CDN費用夠給團隊發幾次下午茶了。
Gzip是HTTP/1.1引入的內容編碼機制,通過DEFLATE算法對響應體進行壓縮。文本類內容(HTML、CSS、JS、JSON、XML)壓縮率通常能達到60%-80%,這意味著原本100KB的文件傳輸時只需要20-40KB。在移動網絡環境下,這個優化效果特別明顯。
現代瀏覽器都支持Gzip解壓,服務端壓縮+客戶端解壓這個過程對用戶來說完全透明,但帶來的體驗提升卻是實實在在的。
1.2 技術特點
壓縮原理
Gzip基于LZ77算法和哈夫曼編碼,通過查找重復字符串并用更短的引用替代,再對結果進行熵編碼。對于包含大量重復模式的文本文件效果最好,對已經壓縮過的文件(圖片、視頻、壓縮包)幾乎沒有效果。
壓縮級別
Nginx支持1-9九個壓縮級別:
級別1:壓縮速度最快,壓縮率最低
級別9:壓縮率最高,但CPU消耗也最大
級別5-6:通常是性能和壓縮率的最佳平衡點
實測數據顯示,從級別5到級別9,壓縮率只提升3-5%,但CPU消耗增加40%以上。所以生產環境一般不建議用9。
靜態預壓縮
Nginx的gzip_static模塊支持預壓縮文件。如果存在file.js.gz,直接返回壓縮文件而不用實時壓縮,徹底消除CPU開銷。這是高并發場景下的殺手級優化。
1.3 適用場景
適合Gzip壓縮的內容
HTML/CSS/JavaScript
JSON/XML/SVG
純文本文件(txt、csv、log)
字體文件(woff雖然已壓縮,但gzip還能再壓10%左右)
不適合Gzip壓縮的內容
圖片(JPEG、PNG、WebP本身已壓縮)
視頻/音頻文件
壓縮包(zip、gz、rar)
PDF文件(內部已壓縮)
典型應用場景
API服務器:JSON響應壓縮效果極佳
靜態資源服務器:CSS/JS壓縮節省大量帶寬
文檔站點:HTML內容壓縮率高
日志分析平臺:大量文本數據傳輸
1.4 環境要求
| 組件 | 版本要求 | 說明 |
|---|---|---|
| 操作系統 | Rocky Linux 9 / Ubuntu 24.04 LTS | 內核4.x以上 |
| Nginx | 1.26.x / 1.27.x | 需包含ngx_http_gzip_module |
| 可選模塊 | gzip_static | 靜態預壓縮支持 |
| 可選模塊 | gunzip | 為不支持gzip的客戶端解壓 |
| CPU | 多核推薦 | 實時壓縮消耗CPU |
| 內存 | 每連接約256KB | gzip緩沖區大小 |
二、詳細步驟
2.1 準備工作
確認Nginx已編譯gzip模塊
# 查看編譯參數 nginx -V 2>&1 | tr' '' '| grep gzip # 輸出應包含: # --with-http_gzip_static_module # --with-http_gunzip_module # 如果缺少gzip_static模塊,需要重新編譯或安裝帶模塊的版本 # 官方倉庫的nginx默認包含這些模塊
準備測試文件
# 創建測試目錄 mkdir -p /data/gzip-test # 生成測試文件 cat > /data/gzip-test/test.html <'EOF'Gzip壓縮測試 EOF # 創建一個大的JS文件用于測試 curl -o /data/gzip-test/jquery.js https://code.jquery.com/jquery-3.7.1.js 2>/dev/null ||echo'console.log("test");'> /data/gzip-test/jquery.js # 創建JSON測試文件 cat > /data/gzip-test/data.json <'EOF' { ? ??"users": [ ? ? ? ? {"id": 1,?"name":?"張三",?"email":?"zhangsan@example.com"}, ? ? ? ? {"id": 2,?"name":?"李四",?"email":?"lisi@example.com"}, ? ? ? ? {"id": 3,?"name":?"王五",?"email":?"wangwu@example.com"} ? ? ], ? ??"total": 3, ? ??"page": 1, ? ??"pageSize": 10 } EOF # 查看文件大小 ls -lh /data/gzip-test/Gzip壓縮效果測試頁面
安裝測試工具
# Rocky Linux dnf install curl httpd-tools -y # Ubuntu apt install curl apache2-utils -y
2.2 核心配置
基礎Gzip配置
# /etc/nginx/nginx.conf 或 /etc/nginx/conf.d/gzip.conf
http {
# ==================== Gzip基礎配置 ====================
# 開啟gzip壓縮
gzip on;
# 壓縮級別:1-9,推薦5-6
# 級別越高壓縮率越好但CPU消耗越大
gzip_comp_level 5;
# 最小壓縮文件大小
# 小于這個值的文件不壓縮(壓縮收益?。? gzip_min_length 1024;
# 壓縮緩沖區
# 32個4k的緩沖區,用于存儲壓縮結果
gzip_buffers 32 4k;
# 壓縮HTTP版本
# 對HTTP/1.0也啟用壓縮(兼容老代理)
gzip_http_version 1.0;
# ==================== 壓縮類型配置 ====================
# 需要壓縮的MIME類型
# 注意:text/html默認已啟用,不需要重復添加
gzip_types
# 文本類型
text/plain
text/css
text/xml
text/javascript
# 應用類型
application/json
application/javascript
application/x-javascript
application/xml
application/xml+rss
application/xhtml+xml
application/atom+xml
application/rss+xml
# 字體類型
application/font-woff
application/font-woff2
application/vnd.ms-fontobject
application/x-font-ttf
font/opentype
font/woff
font/woff2
# 圖片類型(僅SVG,其他圖片已壓縮)
image/svg+xml
image/x-icon;
# ==================== 代理相關配置 ====================
# 針對代理請求的壓縮策略
# any: 對所有代理請求都壓縮
gzip_proxied any;
# 其他可選值:
# off: 禁止對代理請求壓縮
# expired: 響應頭包含Expires且已過期
# no-cache: 響應頭包含Cache-Control: no-cache
# no-store: 響應頭包含Cache-Control: no-store
# private: 響應頭包含Cache-Control: private
# no_last_modified: 響應頭不包含Last-Modified
# no_etag: 響應頭不包含ETag
# auth: 請求頭包含Authorization
# any: 所有代理請求
# ==================== Vary頭配置 ====================
# 在響應頭中添加Vary: Accept-Encoding
# 告訴代理服務器根據Accept-Encoding緩存不同版本
gzip_vary on;
# ==================== 排除特定客戶端 ====================
# 禁止對特定User-Agent壓縮
# 某些老舊瀏覽器對gzip支持有問題
gzip_disable "MSIE [1-6].";
# 也可以用正則排除更多
# gzip_disable "MSIE [1-6].|Mozilla/4";
}
靜態預壓縮配置(gzip_static)
這是我強烈推薦的優化方式,特別是對于前端構建產物:
http {
# 開啟靜態預壓縮
# on: 查找.gz文件,找到就直接返回
# off: 禁用
# always: 始終返回.gz文件,不檢查客戶端是否支持
gzip_static on;
server {
listen 80;
server_name example.com;
root /data/www;
# 前端資源目錄
location /assets/ {
# 啟用靜態預壓縮
gzip_static on;
# 緩存控制
expires 1y;
add_header Cache-Control "public, immutable";
}
# API接口(實時壓縮)
location /api/ {
# API響應需要實時壓縮
gzip on;
gzip_comp_level 5;
gzip_types application/json;
proxy_pass http://backend;
}
}
}
預壓縮文件生成腳本
#!/bin/bash
# generate_gzip.sh - 生成預壓縮文件
STATIC_DIR=${1:-/data/www/assets}
GZIP_LEVEL=${2:-9}
echo"開始生成預壓縮文件..."
echo"目錄:$STATIC_DIR"
echo"壓縮級別:$GZIP_LEVEL"
# 需要預壓縮的文件類型
FILE_TYPES="css js html json xml svg txt"
forextin$FILE_TYPES;do
find"$STATIC_DIR"-name"*.$ext"-typef |whilereadfile;do
# 跳過已經是.gz的文件
[["$file"== *.gz ]] &&continue
gz_file="${file}.gz"
# 如果.gz文件不存在或源文件更新,重新壓縮
if[[ ! -f"$gz_file"]] || [["$file"-nt"$gz_file"]];then
echo"壓縮:$file"
gzip -${GZIP_LEVEL}-c"$file">"$gz_file"
# 保持時間戳一致
touch -r"$file""$gz_file"
fi
done
done
echo"預壓縮完成!"
# 統計壓縮效果
echo""
echo"=== 壓縮效果統計 ==="
find"$STATIC_DIR"-name"*.gz"-typef |whilereadgz_file;do
orig_file="${gz_file%.gz}"
if[[ -f"$orig_file"]];then
orig_size=$(stat-c%s"$orig_file"2>/dev/null ||stat-f%z"$orig_file")
gz_size=$(stat-c%s"$gz_file"2>/dev/null ||stat-f%z"$gz_file")
ratio=$(echo"scale=2; (1 -$gz_size/$orig_size) * 100"| bc)
echo"$orig_file:$orig_size->$gz_size(節省${ratio}%)"
fi
done
2.3 啟動和驗證
配置檢查
# 檢查配置語法 nginx -t # 查看gzip相關配置 nginx -T | grep -i gzip # 重載配置 nginx -s reload
基礎驗證
# 測試gzip是否生效 # 注意:必須發送Accept-Encoding頭 # 不帶壓縮請求 curl -I http://localhost/test.html # Content-Length: 1234 (原始大?。? # 帶壓縮請求 curl -I -H"Accept-Encoding: gzip"http://localhost/test.html # Content-Encoding: gzip # Content-Length: 456 (壓縮后大小) # Vary: Accept-Encoding # 獲取完整響應并解壓 curl -H"Accept-Encoding: gzip"http://localhost/test.html | gunzip
詳細測試腳本
#!/bin/bash
# test_gzip.sh - 測試Gzip壓縮效果
URL=${1//localhost}
FILES=("test.html""jquery.js""data.json""style.css")
echo"=== Gzip壓縮效果測試 ==="
echo"目標:$URL"
echo""
printf"%-30s %10s %10s %10s
""文件""原始大小""壓縮大小""壓縮率"
printf"%-30s %10s %10s %10s
""----""--------""--------""------"
forfilein"${FILES[@]}";do
# 獲取未壓縮大小
orig_size=$(curl -sI"$URL/$file"2>/dev/null | grep -i content-length | awk'{print $2}'| tr -d'
')
# 獲取壓縮后大小
gzip_size=$(curl -sI -H"Accept-Encoding: gzip""$URL/$file"2>/dev/null | grep -i content-length | awk'{print $2}'| tr -d'
')
# 檢查是否啟用了壓縮
encoding=$(curl -sI -H"Accept-Encoding: gzip""$URL/$file"2>/dev/null | grep -i content-encoding)
if[[ -n"$encoding"]] && [[ -n"$orig_size"]] && [[ -n"$gzip_size"]];then
ratio=$(echo"scale=1; (1 -$gzip_size/$orig_size) * 100"| bc)
printf"%-30s %10s %10s %9s%%
""$file""$orig_size""$gzip_size""$ratio"
else
printf"%-30s %10s %10s %10s
""$file""$orig_size""${gzip_size:-N/A}""未壓縮"
fi
done
壓力測試對比
# 無壓縮測試 ab -n 10000 -c 100 http://localhost/jquery.js # 記錄:Requests per second, Transfer rate # 有壓縮測試 ab -n 10000 -c 100 -H"Accept-Encoding: gzip"http://localhost/jquery.js # 記錄:Requests per second, Transfer rate # 對比傳輸量和吞吐量的變化
三、示例代碼和配置
3.1 完整配置示例
生產環境完整配置
# /etc/nginx/conf.d/gzip-production.conf
# 生產環境Gzip完整配置
http {
# ==================== Gzip全局配置 ====================
# 基礎開關
gzip on;
# 壓縮級別:生產環境推薦5
gzip_comp_level 5;
# 最小壓縮大?。盒∮?KB的文件不壓縮
gzip_min_length 1024;
# 壓縮緩沖區配置
# 16個8k的緩沖區,適合中等大小文件
gzip_buffers 16 8k;
# HTTP版本
gzip_http_version 1.1;
# 啟用Vary頭
gzip_vary on;
# 對代理請求的處理
gzip_proxied any;
# 禁用對老舊IE的壓縮
gzip_disable "MSIE [1-6].(?!.*SV1)";
# 壓縮類型(完整列表)
gzip_types
# 文本
text/plain
text/css
text/xml
text/javascript
text/x-component
text/cache-manifest
# 應用
application/json
application/javascript
application/x-javascript
application/xml
application/xml+rss
application/xhtml+xml
application/atom+xml
application/rss+xml
application/ld+json
application/manifest+json
application/schema+json
application/geo+json
application/vnd.api+json
application/vnd.ms-fontobject
application/x-font-ttf
application/x-font-opentype
application/x-font-truetype
application/x-web-app-manifest+json
# 字體
font/eot
font/opentype
font/otf
font/woff
font/woff2
# 圖片(僅矢量)
image/svg+xml
image/x-icon
image/bmp
image/vnd.microsoft.icon;
# ==================== 靜態預壓縮 ====================
# 全局開啟靜態預壓縮
gzip_static on;
}
分場景配置示例
server {
listen 80;
server_name example.com;
root /data/www;
# ==================== 場景一:靜態資源CDN源站 ====================
location /static/ {
# 使用預壓縮文件(最高壓縮級別)
gzip_static on;
# 如果沒有預壓縮文件,實時壓縮
gzip on;
gzip_comp_level 6;
# 長緩存
expires 1y;
add_header Cache-Control "public, immutable";
}
# ==================== 場景二:API響應壓縮 ====================
location /api/ {
# API響應通常是JSON,必須實時壓縮
gzip on;
gzip_comp_level 5;
gzip_min_length 256; # API響應可能較小,降低閾值
gzip_types application/json;
# 禁用代理緩存(API響應經常變化)
add_header Cache-Control "no-store";
proxy_pass http://api_backend;
proxy_set_header Accept-Encoding ""; # 不讓后端壓縮,Nginx統一處理
}
# ==================== 場景三:HTML頁面 ====================
location / {
gzip on;
gzip_comp_level 5;
gzip_types text/html;
# HTML不緩存,保證獲取最新內容
expires -1;
add_header Cache-Control "no-cache, must-revalidate";
try_files $uri $uri/ /index.html;
}
# ==================== 場景四:大文件下載 ====================
location /downloads/ {
# 大文件不壓縮,避免占用大量內存和CPU
gzip off;
# 開啟sendfile高效傳輸
sendfile on;
tcp_nopush on;
# 限速防止帶寬耗盡
limit_rate 1m;
}
# ==================== 場景五:WebSocket ====================
location /ws/ {
# WebSocket不能使用gzip
gzip off;
proxy_pass http://websocket_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
3.2 實際應用案例
案例一:電商網站首頁優化
我們有個電商客戶,首頁HTML有800KB(包含大量商品數據),加載時間超過3秒。
優化前的情況:
首頁大小: 812KB 加載時間: 3.2s(3G網絡) Gzip: 未啟用
優化方案:
location / {
gzip on;
gzip_comp_level 6; # 首頁訪問頻繁,適當提高壓縮級別
gzip_types text/html application/json;
gzip_min_length 256;
# 啟用ETag便于緩存驗證
etag on;
try_files $uri @backend;
}
location @backend {
proxy_pass http://backend;
# 后端響應也要壓縮
gzip on;
gzip_proxied any;
}
優化后:
首頁大小: 812KB -> 156KB(壓縮率81%) 加載時間: 3.2s -> 0.8s 帶寬節省: 約80%
案例二:API服務壓縮優化
某金融APP后端API,每天數千萬次調用,返回JSON數據。
問題分析:
平均響應大小: 15KB 日請求量: 5000萬次 日帶寬消耗: 約700TB 帶寬成本: 高
配置方案:
upstream api_servers {
server 10.0.1.10:8080;
server 10.0.1.11:8080;
keepalive 100;
}
server {
listen 80;
server_name api.example.com;
location / {
# JSON響應壓縮
gzip on;
gzip_comp_level 5;
gzip_min_length 512;
gzip_types application/json;
gzip_proxied any;
gzip_vary on;
proxy_pass http://api_servers;
proxy_http_version 1.1;
proxy_set_header Connection "";
# 重要:告訴后端不要壓縮,統一由Nginx處理
proxy_set_header Accept-Encoding "identity";
# 緩沖設置,避免邊收邊發
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 32k;
}
}
優化效果:
平均響應大小: 15KB -> 3KB(壓縮率80%) 日帶寬消耗: 700TB -> 140TB 月度帶寬成本節省: 約560TB * 單價 CPU增加: 約15%(可接受)
案例三:前端構建產物預壓縮
現代前端項目使用Webpack/Vite構建,結合CI/CD自動生成預壓縮文件。
Vite配置:
// vite.config.js
import{ defineConfig }from'vite'
importviteCompressionfrom'vite-plugin-compression'
exportdefaultdefineConfig({
plugins: [
viteCompression({
algorithm:'gzip',
ext:'.gz',
threshold:1024, // 大于1KB才壓縮
deleteOriginFile:false// 保留原文件
}),
// 同時生成Brotli壓縮
viteCompression({
algorithm:'brotliCompress',
ext:'.br',
threshold:1024
})
]
})
Nginx配置:
location /assets/ {
# 優先返回Brotli壓縮(壓縮率更高)
brotli_static on;
# 其次返回Gzip
gzip_static on;
# 如果都沒有,實時壓縮
gzip on;
gzip_comp_level 5;
expires max;
add_header Cache-Control "public, immutable";
}
CI/CD pipeline腳本:
#!/bin/bash
# build.sh - 前端構建腳本
# 構建
npm run build
# 生成預壓縮文件
cddist
# Gzip壓縮
find . -typef ( -name"*.js"-o -name"*.css"-o -name"*.html"-o -name"*.json")
-execgzip -9 -k {} ;
# Brotli壓縮(如果安裝了brotli)
ifcommand-v brotli &> /dev/null;then
find . -typef ( -name"*.js"-o -name"*.css"-o -name"*.html"-o -name"*.json")
-execbrotli -9 -k {} ;
fi
# 統計
echo"=== 壓縮統計 ==="
du -sh dist/
find dist -name"*.gz"| wc -l
find dist -name"*.br"| wc -l
案例四:不同壓縮級別性能對比測試
我在一臺4核8G的服務器上做了詳細測試,文件是280KB的jquery.min.js:
| 壓縮級別 | 壓縮后大小 | 壓縮率 | 壓縮耗時 | QPS |
|---|---|---|---|---|
| 1 | 98KB | 65% | 0.8ms | 12000 |
| 2 | 94KB | 66% | 0.9ms | 11500 |
| 3 | 91KB | 67% | 1.1ms | 10800 |
| 4 | 88KB | 69% | 1.4ms | 9500 |
| 5 | 85KB | 70% | 1.8ms | 8200 |
| 6 | 84KB | 70% | 2.5ms | 6800 |
| 7 | 83KB | 70% | 3.8ms | 5200 |
| 8 | 82KB | 71% | 6.2ms | 3500 |
| 9 | 82KB | 71% | 12ms | 1800 |
| 預壓縮 | 82KB | 71% | 0ms | 35000 |
結論:
級別5是性價比最高的選擇
級別6-9收益遞減明顯,不推薦
預壓縮性能碾壓實時壓縮,強烈推薦
四、最佳實踐和注意事項
4.1 最佳實踐
1. 根據內容類型選擇壓縮策略
# 高頻訪問的靜態資源:預壓縮
location ~* .(js|css)$ {
gzip_static on;
gzip on;
gzip_comp_level 5;
}
# 動態生成的內容:實時壓縮
location /api/ {
gzip on;
gzip_comp_level 5;
}
# 已壓縮的媒體文件:不壓縮
location ~* .(jpg|jpeg|png|gif|mp4|webm|zip|gz)$ {
gzip off;
}
2. 合理設置gzip_min_length
# 太小的文件壓縮后可能反而變大(gzip頭部開銷) # 推薦設置: gzip_min_length 1024; # 通用場景 # API場景可以降低閾值(JSON通常較小但壓縮率高) gzip_min_length 256;
3. gzip_vary必須開啟
# 必須開啟,否則CDN/代理可能返回錯誤的緩存 gzip_vary on; # 這會在響應頭添加: # Vary: Accept-Encoding # 告訴緩存服務器:同一URL根據Accept-Encoding返回不同內容
4. 統一在Nginx層壓縮
# 不要讓后端應用也壓縮,會造成:
# 1. 重復壓縮浪費CPU
# 2. 壓縮策略不統一
# 3. 調試困難
location /api/ {
proxy_pass http://backend;
# 告訴后端不要壓縮
proxy_set_header Accept-Encoding "identity";
# 由Nginx統一壓縮
gzip on;
gzip_proxied any;
}
5. 監控壓縮效果
# 自定義日志格式記錄壓縮信息
log_format compression '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$gzip_ratio';
# $gzip_ratio 顯示壓縮比例,如 "2.50"表示壓縮到原來的1/2.5
4.2 注意事項
常見錯誤表
| 錯誤 | 原因 | 解決方案 |
|---|---|---|
| gzip不生效 | 請求頭缺少Accept-Encoding | 檢查客戶端/代理是否移除了該頭 |
| 壓縮率低 | 文件已壓縮或內容隨機性高 | 檢查文件類型,已壓縮文件不要重復壓縮 |
| CPU飆高 | 壓縮級別過高或并發過大 | 降低壓縮級別或使用預壓縮 |
| 響應變慢 | gzip_buffers配置不當 | 增大緩沖區或降低壓縮級別 |
| CDN緩存異常 | 未設置Vary頭 | 開啟gzip_vary on |
| 部分請求未壓縮 | 小于gzip_min_length | 降低閾值或接受不壓縮 |
| 亂碼 | 客戶端不支持gzip | 使用gzip_disable排除 |
性能陷阱
# 陷阱1:對所有內容都壓縮 # 錯誤 gzip_types *; # 正確:只壓縮文本類型 # 陷阱2:壓縮級別設置過高 # 錯誤 gzip_comp_level 9; # CPU殺手 # 正確 gzip_comp_level 5; # 性價比最高 # 陷阱3:不限制最小壓縮大小 # 錯誤 gzip_min_length 0; # 所有文件都壓縮 # 正確 gzip_min_length 1024; # 小文件不壓縮 # 陷阱4:對圖片視頻壓縮 # 錯誤 gzip_types image/jpeg image/png video/mp4; # 這些格式已經壓縮過,再壓縮只浪費CPU # 陷阱5:沒有預壓縮高頻文件 # 錯誤:每次請求都實時壓縮 # 正確:構建時預壓縮 + gzip_static on
安全考慮
# BREACH攻擊防護
# 對包含敏感信息的HTTPS響應,攻擊者可能通過壓縮率變化推測內容
# 防護方案:
# 1. 對包含敏感數據的響應禁用壓縮
location /api/sensitive/ {
gzip off;
}
# 2. 在響應中添加隨機填充
# 需要后端配合實現
# 3. 使用SameSite Cookie
add_header Set-Cookie "session=xxx; SameSite=Strict";
五、故障排查和監控
5.1 故障排查
問題一:Gzip完全不生效
# 排查步驟 # 1. 檢查模塊是否加載 nginx -V 2>&1 | grep -o'http_gzip_module' # 2. 檢查配置是否生效 nginx -T | grep gzip # 3. 測試請求 curl -I -H"Accept-Encoding: gzip"http://localhost/test.html # 4. 如果響應頭沒有Content-Encoding: gzip,檢查: # - gzip是否為on # - 文件類型是否在gzip_types中 # - 文件大小是否大于gzip_min_length # - 是否被gzip_disable規則排除 # 5. 查看錯誤日志 tail -f /var/log/nginx/error.log
問題二:部分文件未壓縮
# 常見原因:MIME類型不在gzip_types中 # 檢查文件MIME類型 file --mime-type test.json # application/json # 檢查Nginx的MIME配置 cat /etc/nginx/mime.types | grep json # 確保gzip_types包含該類型 nginx -T | grep gzip_types
問題三:壓縮后文件變大
# 小文件或高熵內容壓縮后可能變大 # 檢查原始文件大小 ls -la test.html # 如果小于1KB,提高gzip_min_length # 或者檢查文件內容是否已壓縮/隨機數據
問題四:CPU占用過高
# 檢查壓縮級別 nginx -T | grep gzip_comp_level # 查看Nginx進程CPU top -p $(pgrep -d','nginx) # 解決方案: # 1. 降低壓縮級別 # 2. 使用預壓縮 # 3. 增加gzip_min_length # 4. 限制壓縮類型
調試腳本
#!/bin/bash # debug_gzip.sh - Gzip配置調試 URL=$1 if[ -z"$URL"];then echo"用法:$0" exit1 fi echo"=== Gzip調試:$URL===" echo"" echo"--- 請求頭 ---" curl -sI"$URL"| head -20 echo"" echo"--- 帶Accept-Encoding的請求 ---" curl -sI -H"Accept-Encoding: gzip, deflate""$URL"| head -20 echo"" echo"--- 關鍵響應頭 ---" echo"Content-Encoding:$(curl -sI -H 'Accept-Encoding: gzip' "$URL" | grep -i content-encoding)" echo"Content-Length (原始):$(curl -sI "$URL" | grep -i content-length)" echo"Content-Length (壓縮):$(curl -sI -H 'Accept-Encoding: gzip' "$URL" | grep -i content-length)" echo"Vary:$(curl -sI -H 'Accept-Encoding: gzip' "$URL" | grep -i vary)" echo"" echo"--- 內容類型 ---" echo"Content-Type:$(curl -sI "$URL" | grep -i content-type)"
5.2 性能監控
Nginx狀態監控
# 啟用狀態頁
location /nginx_status {
stub_status on;
allow 127.0.0.1;
deny all;
}
壓縮率日志
# 記錄壓縮比例
log_format gzip_log '$remote_addr [$time_local] "$request" '
'$status $body_bytes_sent '
'gzip_ratio=$gzip_ratio '
'rt=$request_time';
access_log /var/log/nginx/gzip.log gzip_log;
分析腳本
#!/bin/bash
# analyze_gzip.sh - 分析Gzip壓縮效果
LOG_FILE=${1:-/var/log/nginx/gzip.log}
echo"=== Gzip壓縮效果分析 ==="
echo""
echo"--- 壓縮比例分布 ---"
awk'{
for(i=1;i<=NF;i++) {
? ? ? ? if($i ~ /gzip_ratio=/) {
? ? ? ? ? ? split($i, a, "=")
? ? ? ? ? ? ratio = a[2]
? ? ? ? ? ? if (ratio == "-") {
? ? ? ? ? ? ? ? none++
? ? ? ? ? ? } else if (ratio < 1.5) {
? ? ? ? ? ? ? ? low++
? ? ? ? ? ? } else if (ratio < 3) {
? ? ? ? ? ? ? ? medium++
? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? high++
? ? ? ? ? ? }
? ? ? ? }
? ? }
}
END {
? ? total = none + low + medium + high
? ? printf "未壓縮: %d (%.1f%%)
", none, none/total*100
? ? printf "低壓縮(<1.5x): %d (%.1f%%)
", low, low/total*100
? ? printf "中壓縮(1.5-3x): %d (%.1f%%)
", medium, medium/total*100
? ? printf "高壓縮(>3x): %d (%.1f%%)
", high, high/total*100
}'$LOG_FILE
echo""
echo"--- 按文件類型統計 ---"
awk'{
# 提取URL和壓縮比
url = $5
gsub(/"/, "", url)
for(i=1;i<=NF;i++) {
? ? ? ? if($i ~ /gzip_ratio=/) {
? ? ? ? ? ? split($i, a, "=")
? ? ? ? ? ? ratio = a[2]
? ? ? ? }
? ? }
? ? # 提取擴展名
? ? n = split(url, parts, ".")
? ? ext = parts[n]
? ? n = split(ext, parts, "?")
? ? ext = parts[1]
? ? if (ratio != "-" && ratio > 0) {
count[ext]++
sum[ext] += ratio
}
}
END {
printf "%-10s %10s %15s
", "類型", "請求數", "平均壓縮比"
for (ext in count) {
printf "%-10s %10d %15.2f
", ext, count[ext], sum[ext]/count[ext]
}
}'$LOG_FILE| sort -t$' '-k2 -rn
Prometheus監控指標
# prometheus.yml 抓取配置 scrape_configs: -job_name:'nginx' static_configs: -targets:['localhost:9113'] # 自定義指標(需要nginx-prometheus-exporter) # nginx_http_requests_total # nginx_connections_active # nginx_connections_reading # nginx_connections_writing
5.3 備份與恢復
配置備份
#!/bin/bash # backup_gzip_config.sh BACKUP_DIR="/backup/nginx/gzip" DATE=$(date +%Y%m%d) mkdir -p$BACKUP_DIR # 備份gzip相關配置 nginx -T | grep -A 100'gzip'>$BACKUP_DIR/gzip_config_$DATE.txt # 備份完整配置 cp -r /etc/nginx/conf.d/$BACKUP_DIR/conf.d_$DATE/ # 保留30天 find$BACKUP_DIR-mtime +30 -delete echo"備份完成:$BACKUP_DIR"
快速回滾
#!/bin/bash # rollback_gzip.sh - 回滾到默認gzip配置 cat > /etc/nginx/conf.d/gzip.conf <'EOF' # Gzip默認配置 gzip on; gzip_comp_level 5; gzip_min_length 1024; gzip_types text/plain text/css application/json application/javascript text/xml; gzip_vary on; EOF nginx -t && nginx -s reload echo?"已回滾到默認gzip配置"
六、總結
6.1 技術要點回顧
Gzip壓縮優化的核心就是這幾點:
選對壓縮級別:生產環境用5-6,別用9
選對壓縮類型:只壓縮文本類,別碰圖片視頻
用好預壓縮:高頻訪問的靜態資源必須預壓縮
開啟Vary頭:gzip_vary on必須有
統一入口壓縮:在Nginx層統一處理,后端不壓縮
關鍵配置速記:
gzip on; gzip_comp_level 5; gzip_min_length 1024; gzip_types text/plain text/css application/json application/javascript; gzip_vary on; gzip_static on;
6.2 進階學習方向
Brotli壓縮:比Gzip壓縮率高15-20%,現代瀏覽器都支持
Zstd壓縮:Facebook開源的新一代壓縮算法
動態壓縮級別:根據CPU負載動態調整壓縮級別
邊緣壓縮:在CDN邊緣節點進行壓縮
6.3 參考資料
Nginx Gzip模塊文檔:https://nginx.org/en/docs/http/ngx_http_gzip_module.html
Gzip vs Brotli對比:https://www.keycdn.com/blog/brotli-compression
HTTP壓縮機制RFC:https://tools.ietf.org/html/rfc7231#section-3.1.2.2
BREACH攻擊說明:https://breachattack.com/
附錄
A. 命令速查表
| 命令 | 說明 |
|---|---|
| gzip -9 file.js | 壓縮文件(最高級別) |
| gzip -k file.js | 壓縮并保留原文件 |
| gzip -l file.js.gz | 查看壓縮信息 |
| gunzip file.js.gz | 解壓文件 |
| zcat file.js.gz | 查看壓縮文件內容 |
| curl -I -H "Accept-Encoding: gzip" URL | 測試gzip是否生效 |
B. 配置參數詳解
| 參數 | 默認值 | 說明 |
|---|---|---|
| gzip | off | 開啟/關閉gzip |
| gzip_comp_level | 1 | 壓縮級別1-9 |
| gzip_min_length | 20 | 最小壓縮大?。ㄗ止潱?/td> |
| gzip_buffers | 32 4k | 壓縮緩沖區配置 |
| gzip_types | text/html | 壓縮的MIME類型 |
| gzip_vary | off | 是否添加Vary頭 |
| gzip_proxied | off | 代理請求壓縮策略 |
| gzip_disable | - | 禁用壓縮的User-Agent |
| gzip_http_version | 1.1 | 啟用壓縮的最低HTTP版本 |
| gzip_static | off | 靜態預壓縮開關 |
C. 術語表
| 術語 | 解釋 |
|---|---|
| Gzip | GNU zip,一種基于DEFLATE算法的壓縮格式 |
| DEFLATE | 結合LZ77和霍夫曼編碼的壓縮算法 |
| Content-Encoding | HTTP響應頭,指示內容的編碼方式 |
| Accept-Encoding | HTTP請求頭,告知服務器客戶端支持的編碼 |
| Vary | HTTP響應頭,指示緩存應根據哪些請求頭區分響應 |
| Transfer-Encoding | 傳輸編碼,chunked表示分塊傳輸 |
| MIME Type | 多用途互聯網郵件擴展類型,標識內容格式 |
| Brotli | Google開發的新一代壓縮算法,壓縮率優于Gzip |
-
算法
+關注
關注
23文章
4784瀏覽量
98038 -
字符串
+關注
關注
1文章
596瀏覽量
23165 -
nginx
+關注
關注
0文章
186瀏覽量
13110
原文標題:Nginx Gzip壓縮配置指南:流量節省60%的秘密
文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
如何使用GZip的比特流完成重新配置?
nginx錯誤頁面配置
主要學習下nginx的安裝配置
運行nginx所需的最低配置
Spring Boot+Filter實現Gzip壓縮超大json對象
Nginx常用的配置和基本功能講解
深入淺出了解華為云 API 網關的 Gzip 功能
Nginx Gzip壓縮配置指南
評論