第三章 分场景实操(会落地)
前两章已拆解"压缩与缓存"的底层逻辑(原理透视)和问题定位方法(痛点深挖),本章聚焦"落地执行"------针对16类主流场景中的高频场景,提供"可复制的配置脚本+跨版本适配技巧+步骤化验证方案"。无论你是新手(直接抄作业)还是老手(适配分布式场景),都能通过本章实现"配置即生效,问题可验证"。
💡 核心落地原则:先定场景核心诉求(如直播场景求低延迟,点播场景求高压缩率)→ 选对应技术方案(如直播用H.264,点播用H.265)→ 配最小化生效配置→ 验证后再优化,避免一上来堆砌复杂配置导致排障困难。
3.1 Web服务器场景:Nginx/Apache/Tomcat全适配
Web服务器是压缩与缓存的"第一关",不同服务器的模块差异较大(如Nginx需编译Brotli模块,Apache自带压缩模块),本节覆盖三大主流服务器,适配最新稳定版本(Nginx 1.20-1.26、Apache 2.2/2.4、Tomcat 8-10)。
3.1.1 Nginx场景(最主流,适配90%Web服务)
Nginx的压缩依赖ngx_http_gzip_module(默认内置)和ngx_http_brotli_module(需额外编译),缓存依赖ngx_http_headers_module(默认内置)。核心诉求:静态资源高压缩率+长缓存,动态页面协商缓存。
1. 压缩配置:Brotli+gzip双算法动态适配
目标:现代浏览器返回Brotli(压缩率高),老旧浏览器返回gzip(兼容性好),小文件不压缩(避免开销>收益)。
# 1. 加载模块(Nginx 1.20+可通过yum安装:yum install nginx-module-brotli)
load_module modules/ngx_http_brotli_filter_module.so; # 动态压缩模块
load_module modules/ngx_http_brotli_static_module.so; # 静态预压缩模块
http {
# 2. gzip基础配置(适配IE8等老旧终端)
gzip on;
gzip_vary on; # 告诉CDN区分压缩格式缓存(关键)
gzip_types text/html text/css application/javascript image/svg+xml font/ttf application/json; # 需压缩的类型
gzip_comp_level 6; # 平衡级(1最快,9压缩率最高)
gzip_min_length 1024; # <1KB不压缩
gzip_buffers 4 16k; # 压缩缓冲区大小(适配小内存服务器)
# 3. Brotli配置(现代终端最优)
brotli on;
brotli_vary on;
brotli_types text/html text/css application/javascript image/svg+xml font/ttf application/json;
brotli_comp_level 11; # 现代终端CPU强,用最高压缩率
brotli_min_length 1024;
brotli_buffers 4 16k;
# 4. 静态资源路径匹配(如/static/目录)
location ~* ^/static/ {
root /usr/share/nginx/html;
expires 30d; # 配合缓存用长有效期
}
}
# 版本适配说明:
# - Nginx 1.20-1.26:直接yum安装brotli模块,无需手动编译
# - 低于1.20版本:需下载brotli源码(https://github.com/google/ngx_brotli),编译时指定--add-module=模块路径
# - 容器化Nginx:在Dockerfile中通过RUN命令编译安装模块
2. 缓存配置:静态资源长缓存+动态页面协商缓存
目标:JS/CSS/图片等静态资源用"版本号+30天强制缓存",商品详情页等动态页面用"60秒强制缓存+协商缓存"。
http {
# 启用ETag和Last-Modified(协商缓存核心)
etag on;
etag_hash_algo md5; # 统一哈希算法,分布式部署不混乱
if_modified_since exact; # 精确匹配修改时间
# 1. 静态资源:版本号+长强制缓存
location ~* \.(js|css|png|jpg|jpeg|gif|woff|ttf)$ {
root /usr/share/nginx/html;
# public允许CDN缓存,max-age=30天
add_header Cache-Control "public, max-age=2592000";
# 版本号文件(如app.123.js)超长期缓存(1年)
if ($request_uri ~* "\.(js|css)\.[0-9a-f]{8}\.(js|css)$") {
add_header Cache-Control "public, max-age=31536000";
}
# 禁止缓存动态参数资源(如?ver=1.0,避免缓存冗余)
if ($request_uri ~* "\?ver=") {
add_header Cache-Control "no-cache";
}
}
# 2. 动态页面(商品详情页,路径含/product/)
location ~* /product/ {
root /usr/share/nginx/html;
# 60秒强制缓存+协商缓存(兼顾性能与实时性)
add_header Cache-Control "private, max-age=60, no-cache";
etag_use_inode off; # 不包含inode,避免同一文件不同标识
}
# 3. 敏感页面(登录/支付):完全不缓存
location ~* /(login|pay)/ {
root /usr/share/nginx/html;
add_header Cache-Control "no-store, no-cache";
expires off;
}
}
⚠️ 避坑点:版本号必须是"文件名内嵌"(如app.123.js),而非URL参数(如app.js?ver=1.23),后者会导致CDN缓存冗余
3. 验证方案:3步确认生效
- 压缩验证 :用curl模拟不同浏览器请求
`# 现代浏览器(支持Brotli)
curl -I -H "Accept-Encoding: br,gzip" https://example.com/static/app.123.js
预期响应头:Content-Encoding: br
老旧浏览器(仅支持gzip)
curl -I -H "Accept-Encoding: gzip" https://example.com/static/app.123.js
预期响应头:Content-Encoding: gzip`
-
缓存验证 :浏览器F12→Network→刷新页面
静态资源:Status Code为200 OK (from disk cache),Cache-Control为max-age=31536000
-
动态页面:首次200 OK,60秒内二次请求200 OK (from disk cache),60秒后304 Not Modified
-
分布式验证 :多台Nginx节点执行以下命令,确认ETag一致
`curl -I https://node1.example.com/static/app.123.js | grep ETag
curl -I https://node2.example.com/static/app.123.js | grep ETag
预期输出:两台节点ETag完全一致(如ETag: "5f8d02a37f4b9")`
3.1.2 Apache场景(政企内网常用,适配2.2/2.4)
Apache的压缩依赖mod_deflate(gzip,默认内置)和mod_brotli(需手动启用),缓存依赖mod_expires和mod_headers。核心差异:Apache配置用.htaccess(虚拟主机级)或httpd.conf(全局级)。
1. 压缩配置:mod_deflate+mod_brotli适配
# 1. 启用模块(httpd.conf全局配置)
LoadModule deflate_module modules/mod_deflate.so
LoadModule brotli_module modules/mod_brotli.so
LoadModule headers_module modules/mod_headers.so
# 2. 全局压缩规则
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/css application/javascript
DeflateCompressionLevel 6 # gzip压缩级别
DeflateMinLength 1024 # <1KB不压缩
# 告诉客户端支持压缩(CDN适配)
Header append Vary Accept-Encoding
</IfModule>
<IfModule mod_brotli.c>
AddOutputFilterByType BROTLI_COMPRESS text/html text/css application/javascript
BrotliCompressionLevel 11 # Brotli压缩级别
BrotliMinLength 1024
Header append Vary Accept-Encoding
</IfModule>
# 3. 虚拟主机级配置(.htaccess文件,放在网站根目录)
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE application/json font/ttf
</IfModule>
# 版本适配说明:
# - Apache 2.4:直接LoadModule启用模块,权限控制用Require all granted
# - Apache 2.2:模块启用相同,但权限控制用Order allow,deny + Allow from all
# - 无mod_brotli模块:需从Apache官网下载对应版本模块,放入modules目录
2. 缓存配置:mod_expires+mod_headers组合
# 1. 启用模块(httpd.conf)
LoadModule expires_module modules/mod_expires.so
# 2. 全局缓存规则
<IfModule mod_expires.c>
ExpiresActive On # 启用缓存
# 静态资源:30天有效期
ExpiresByType text/css "access plus 30 days"
ExpiresByType application/javascript "access plus 30 days"
ExpiresByType image/png "access plus 30 days"
# 动态页面:无强制缓存(触发协商)
ExpiresByType text/html "access plus 0 seconds"
</IfModule>
# 3. 协商缓存配置(.htaccess)
<IfModule mod_headers.c>
# 静态资源:长强制缓存
<FilesMatch "\.(js|css|png)$">
Header set Cache-Control "public, max-age=2592000"
</FilesMatch>
# 动态页面:协商缓存
<FilesMatch "\.php$">
Header set Cache-Control "private, no-cache"
Header set ETag "" # 若用Last-Modified,可关闭ETag减少计算
Header set Last-Modified "%D" # 动态生成修改时间
</FilesMatch>
# 敏感页面:不缓存
<FilesMatch "(login|pay)\.php$">
Header set Cache-Control "no-store, no-cache"
</FilesMatch>
</IfModule>
⚠️ 避坑点:Apache 2.2中.htaccess生效需在httpd.conf中开启AllowOverride All,否则配置不生效
3. 验证方案:Apache专用命令
bash
# 1. 检查模块是否启用
httpd -M | grep -E "deflate|brotli|expires|headers"
# 预期输出:deflate_module (shared)、brotli_module (shared)等
# 2. 压缩验证(同Nginx的curl命令)
curl -I -H "Accept-Encoding: br" https://example.com/static/style.css
# 预期响应头:Content-Encoding: br
# 3. 缓存验证(浏览器Network面板,同Nginx)
3.1.3 Tomcat场景(JavaWeb专属,适配8-10)
Tomcat的压缩配置在server.xml中(Connector节点),缓存需通过web.xml配置过滤器实现。核心局限:Tomcat压缩性能弱于Nginx,建议生产环境用Nginx反向代理Tomcat,仅在测试环境直接用Tomcat配置。
1. 压缩配置:Connector节点核心参数
XML
# 编辑Tomcat/conf/server.xml
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
# 压缩核心参数
compression="on" # 启用压缩
compressionMinSize="1024" # <1KB不压缩
compressableMimeType="text/html,text/css,application/javascript,application/json" # 可压缩类型
noCompressionUserAgents="gozilla,traviata" # 不压缩的浏览器(老旧爬虫)
compressionLevel="6" # gzip压缩级别(Tomcat不直接支持Brotli,需插件)/>
# 版本适配说明:
# - Tomcat 8-10:压缩参数完全兼容,无需修改
# - 启用Brotli:需添加第三方插件(如tomcat-brotli),放入Tomcat/lib目录,再配置compression="brotli"
# - 高并发优化:在Connector节点添加maxThreads="200" acceptCount="100",避免压缩导致线程阻塞
2. 缓存配置:web.xml过滤器实现
XML
# 编辑Web应用/WEB-INF/web.xml
<filter>
<filter-name>CacheFilter</filter-name>
<filter-class>org.apache.catalina.filters.CacheControlFilter</filter-class>
<init-param>
# 静态资源缓存30天
<param-name>cacheControlMaxAge</param-name>
<param-value>2592000</param-value>
</init-param>
<init-param>
# 静态资源类型
<param-name>cacheControlMappings</param-name>
<param-value>text/css=public; max-age=2592000, application/javascript=public; max-age=2592000</param-value>
</init-param>
<init-param>
# 动态页面协商缓存
<param-name>cacheControlMappings</param-name>
<param-value>text/html=private; no-cache</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CacheFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
# ⚠️ 避坑点:Tomcat 10中JavaEE命名空间改为Jakarta,过滤器类需改为jakarta.servlet.Filter,否则启动报错
3. 验证方案:结合Java代码
bash
# 1. 启动Tomcat,检查日志是否有压缩模块报错
tail -f Tomcat/logs/catalina.out
# 预期无Compression相关错误
# 2. 压缩验证(curl命令)
curl -I -H "Accept-Encoding: gzip" http://localhost:8080/your-app/static/app.js
# 预期响应头:Content-Encoding: gzip
# 3. 缓存验证(浏览器访问http://localhost:8080/your-app/index.jsp,查看Network面板)
3.2 CDN场景:阿里云/腾讯云高频配置
CDN是"压缩与缓存的放大器"------不仅能复用源站配置,还能通过边缘节点实现"就近分发"。本节以阿里云和腾讯云CDN为例,覆盖"压缩增强+缓存优化+动态适配"核心配置,适配90%以上CDN场景。
3.2.1 阿里云CDN场景
核心诉求:边缘节点压缩+智能缓存+终端适配,无需修改源站配置即可实现优化。
1. 压缩配置:Brotli优先+类型精细化控制
-
登录控制台:进入"CDN控制台→域名管理→选择目标域名→性能优化→压缩配置"
-
开启压缩 :
勾选"启用Gzip压缩"和"启用Brotli压缩"
-
压缩类型:勾选"text/html、text/css、application/javascript"等,取消勾选"image/jpeg、image/png"(图片已预压缩,CDN再压缩会失真)
-
压缩级别:Gzip选6级,Brotli选11级(边缘节点性能强,可扛高压缩率)
-
主动压缩:勾选"源站未压缩时CDN主动压缩"(适配源站未配置压缩的场景)
-
保存生效:CDN配置生效时间约5-10分钟,需等待生效后验证
核心技巧:图片资源建议在源站用工具预压缩(如TinyPNG),CDN仅压缩文本类资源,避免二次压缩导致画质损失+性能浪费。
2. 缓存配置:命中率提升至80%+
-
基础缓存配置 :进入"缓存配置→默认缓存规则"
静态资源:设置"缓存时长30天",匹配类型"js、css、png、jpg"
-
动态资源:设置"缓存时长0秒",匹配类型"php、jsp、asp",勾选"触发协商缓存"
-
首页:设置"缓存时长10分钟",匹配路径"/index.html"(兼顾首页性能与更新)
-
高级优化 :
忽略参数:进入"缓存配置→忽略参数",添加"userId、token"等唯一参数(避免同一资源因参数不同导致缓存冗余)
-
缓存键配置:取消勾选"包含Cookie"(静态资源无需区分用户Cookie)
-
刷新策略:配置"URL刷新"(更新资源后手动刷新)和"目录预热"(大促前预热热门资源到边缘节点)
3. 验证方案:CDN日志+curl
bash
# 1. 压缩验证
curl -I -H "Accept-Encoding: br,gzip" https://your-cdn-domain.com/static/app.js
# 预期响应头:Content-Encoding: br,X-Cache: HIT(边缘节点命中)
# 2. 缓存命中率验证
# 进入CDN控制台→监控报表→缓存命中率,查看"边缘命中率"是否≥80%
# 3. 忽略参数验证
curl -I https://your-cdn-domain.com/static/app.js?userId=123
curl -I https://your-cdn-domain.com/static/app.js?userId=456
# 预期两次响应的X-Cache: HIT,且ETag一致(说明复用同一缓存)
3.2.2 腾讯云CDN场景
核心配置与阿里云类似,差异点在于"压缩配置"入口为"性能优化→压缩加速","缓存配置"入口为"缓存配置→缓存规则",以下聚焦差异点配置:
# 1. 压缩配置差异点
- 腾讯云默认支持"智能压缩":自动识别资源类型,文本类用Brotli,图片类不压缩
- 压缩级别:腾讯云Brotli仅支持1-9级,选9级(对应阿里云11级效果)
- 新增"压缩排除":可添加"/api/*"等路径,避免接口数据被压缩
# 2. 缓存配置差异点
- 腾讯云支持"缓存键归一化":自动合并相同资源的不同参数URL(如?ver=1.0和?ver=2.0不会归一化,需手动配置忽略参数)
- 预热刷新:腾讯云"预热"支持批量提交1000个URL,阿里云单次500个
- 缓存监控:腾讯云"监控中心→缓存分析"可查看"各资源类型命中率",便于针对性优化
# 验证方案:同阿里云,curl命令+控制台监控
3.3 云原生场景:容器+K8s全流程适配
云原生场景的核心是"配置可复用+动态扩缩容适配",通过Docker封装压缩缓存配置,K8s实现动态管理,本节以"Nginx容器+K8s"为例,覆盖从构建到部署的全流程。
3.3.1 容器化配置(Docker)
目标:构建包含"Brotli压缩+缓存配置"的Nginx镜像,确保容器启动即生效。
1. 编写Dockerfile
# 基础镜像:Nginx 1.26(含Brotli模块)
FROM nginx:1.26-alpine
# 复制自定义Nginx配置
COPY nginx.conf /etc/nginx/nginx.conf
COPY default.conf /etc/nginx/conf.d/default.conf
# 复制静态资源(若需容器内置,否则挂载宿主机目录)
COPY static /usr/share/nginx/html/static
# 暴露端口
EXPOSE 80 443
# 启动Nginx
CMD ["nginx", "-g", "daemon off;"]
# ⚠️ 避坑点:用alpine版本镜像(体积小,约5MB),避免用centos版本(体积200MB+);Brotli模块需基础镜像已包含,否则需手动编译
2. 编写Nginx配置文件(default.conf)
server {
listen 80;
server_name localhost;
# 压缩配置(同3.1.1节Nginx配置)
gzip on;
brotli on;
gzip_types text/html text/css application/javascript;
brotli_types text/html text/css application/javascript;
gzip_comp_level 6;
brotli_comp_level 11;
# 缓存配置
location ~* \.(js|css|png)$ {
root /usr/share/nginx/html;
add_header Cache-Control "public, max-age=2592000";
etag on;
}
location / {
root /usr/share/nginx/html;
index index.html;
add_header Cache-Control "private, no-cache";
}
}
3. 构建与验证镜像
bash
# 1. 构建镜像
docker build -t nginx-compress-cache:v1 .
# 2. 启动容器
docker run -d -p 80:80 --name nginx-test nginx-compress-cache:v1
# 3. 验证(同3.1.1节Nginx验证)
curl -I -H "Accept-Encoding: br" http://localhost/static/app.js
# 预期响应头:Content-Encoding: br
3.3.2 K8s部署配置
目标:用K8s ConfigMap管理Nginx配置(动态修改无需重建镜像),Deployment实现扩缩容,Service暴露服务。
1. 编写ConfigMap配置(nginx-config.yaml)
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-config
namespace: default
data:
# 存储Nginx配置文件
default.conf: |
server {
listen 80;
server_name localhost;
gzip on;
brotli on;
gzip_types text/html text/css application/javascript;
brotli_types text/html text/css application/javascript;
location ~* \.(js|css|png)$ {
root /usr/share/nginx/html;
add_header Cache-Control "public, max-age=2592000";
}
location / {
root /usr/share/nginx/html;
index index.html;
add_header Cache-Control "private, no-cache";
}
}
nginx.conf: |
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
include /etc/nginx/conf.d/*.conf;
}
2. 编写Deployment配置(nginx-deployment.yaml)
Deployment作为K8s中管理无状态应用的核心资源,主要负责管控Nginx容器副本的全生命周期:通过关联ConfigMap实现配置动态挂载(无需重建镜像即可更新压缩缓存规则),通过副本数设置实现弹性扩缩容,同时搭配资源限制和健康检查确保压缩过程不占用过量资源、服务持续可用。以下是完整配置脚本及关键参数说明:
以下配置脚本在基础部署能力上,重点强化了与压缩缓存适配的细节:通过资源限制防止Brotli高压缩率计算占用过多节点CPU,通过健康检查确保缓存服务持续可用,同时保留副本扩缩容能力以应对流量波动。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deploy
namespace: default
spec:
replicas: 3 # 初始3个副本,应对日常流量;高并发时可动态扩至10+
selector:
matchLabels:
app: nginx # 与Pod标签匹配,确保Service能精准路由
strategy:
rollingUpdate:
maxSurge: 1 # 滚动更新时最多新增1个副本,避免流量波动
maxUnavailable: 0 # 更新过程中不允许不可用副本,保障服务连续性
template:
metadata:
labels:
app: nginx # Pod标签,关联Deployment和Service
spec:
containers:
- name: nginx
image: nginx-compress-cache:v1 # 关联前文构建的压缩缓存镜像
ports:
- containerPort: 80 # 容器内端口,与Nginx配置监听端口一致
# 挂载ConfigMap中的Nginx配置,实现配置热更新
volumeMounts:
- name: nginx-config-volume
mountPath: /etc/nginx/conf.d/default.conf
subPath: default.conf # 精准挂载单个文件,避免覆盖目录
- name: nginx-config-volume
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf
# 资源限制:适配压缩场景的CPU/内存需求
resources:
requests: # 调度时的资源申请,确保节点有足够资源
cpu: "100m" # 压缩计算需基础CPU,100m即0.1核
memory: "128Mi" # 缓存文件暂存需基础内存
limits: # 资源使用上限,防止压缩占用过多资源
cpu: "500m" # Brotli最高压缩率时CPU占用较高,限制0.5核
memory: "256Mi" # 避免缓存文件堆积导致内存溢出
# 健康检查:确保压缩缓存服务正常运行
livenessProbe: # 存活检查,失败则重启容器
httpGet:
path: /health # 建议在Nginx配置健康检查接口
port: 80
initialDelaySeconds: 30 # 容器启动30秒后再检查(确保压缩模块加载完成)
periodSeconds: 10 # 每10秒检查一次
timeoutSeconds: 5 # 超时时间5秒,避免误判
readinessProbe: # 就绪检查,失败则从Service移除
httpGet:
path: /health
port: 80
initialDelaySeconds: 5 # 启动5秒后检查是否可接收请求
periodSeconds: 5
# 关联ConfigMap资源,实现配置与镜像解耦
volumes:
- name: nginx-config-volume
configMap:
name: nginx-config # 关联前文创建的ConfigMap
items: # 明确挂载的配置文件,提升安全性
- key: default.conf
path: default.conf
- key: nginx.conf
path: nginx.conf
3. 编写Service配置(nginx-service.yaml)
Service负责将Deployment管理的Pod暴露为网络服务,适配云原生环境的负载均衡需求。针对压缩缓存场景,需确保请求能均匀分发至各副本,避免单副本因压缩计算过载。
apiVersion: v1
kind: Service
metadata:
name: nginx-service
namespace: default
annotations:
# 云厂商负载均衡器注解(以阿里云为例),适配压缩场景
service.beta.kubernetes.io/alibaba-cloud-loadbalancer-healthy-check-flag: "on"
service.beta.kubernetes.io/alibaba-cloud-loadbalancer-health-check-path: "/health"
spec:
type: LoadBalancer # 生产环境首选,云厂商提供托管负载均衡
selector:
app: nginx # 与Deployment的Pod标签匹配,实现流量路由
ports:
- port: 80 # Service对外暴露端口
targetPort: 80 # 指向Pod内Nginx监听端口
protocol: TCP # 传输层协议,适配HTTP/HTTPS流量
sessionAffinity: None # 关闭会话亲和性,确保请求均匀分发(压缩场景无需会话保持)
loadBalancerIP: "" # 留空则自动分配负载均衡器IP,生产可指定固定IP
4. K8s部署与验证全流程
以下步骤覆盖从配置应用到效果验证的全流程,适配K8s 1.20+版本,新手可直接按步骤执行。
- 应用配置资源
bash
# 1. 创建ConfigMap(配置先行,与镜像解耦)
kubectl apply -f nginx-config.yaml
# 预期输出:configmap/nginx-config created
# 2. 创建Deployment(管理Pod副本)
kubectl apply -f nginx-deployment.yaml
# 预期输出:deployment.apps/nginx-deploy created
# 3. 创建Service(暴露服务)
kubectl apply -f nginx-service.yaml
# 预期输出:service/nginx-service created
- 部署状态检查
bash
# 1. 检查Pod状态(确保所有副本Running)
kubectl get pods -l app=nginx
# 预期输出:3个Pod均为Running状态
# NAME READY STATUS RESTARTS AGE
# nginx-deploy-7f9d6f8d7c-2xqzk 1/1 Running 0 5m
# nginx-deploy-7f9d6f8d7c-5mz7k 1/1 Running 0 5m
# nginx-deploy-7f9d6f8d7c-9p4tq 1/1 Running 0 5m
# 2. 检查Service状态(获取负载均衡器IP)
kubectl get svc nginx-service
# 预期输出:EXTERNAL-IP列显示负载均衡器IP
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
# nginx-service LoadBalancer 10.96.123.45 120.78.90.11 80:30080/TCP 5m
# 3. 检查配置挂载情况(确保ConfigMap已挂载到Pod)
kubectl exec -it <pod-name> -- cat /etc/nginx/conf.d/default.conf
` `# 预期输出:与ConfigMap中的default.conf内容一致`
3. **压缩与缓存效果验证**`# 1. 压缩验证(通过负载均衡器IP访问)
curl -I -H "Accept-Encoding: br,gzip" http://<external-ip>/static/app.js
# 预期响应头:Content-Encoding: br(Brotli压缩生效)
# 同时包含X-Cache: HIT(若已缓存)或MISS(首次请求)
# 2. 缓存验证(多次请求观察状态码)
# 首次请求:200 OK(从Pod获取并缓存)
curl -I http://<external-ip>/static/app.js
# 二次请求:200 OK (from cache)(从Pod缓存获取)
curl -I http://<external-ip>/static/app.js
# 3. 扩缩容验证(模拟高并发场景)
# 扩容至5个副本
kubectl scale deployment nginx-deploy --replicas=5
# 检查副本状态(5个Running)
kubectl get pods -l app=nginx
# 再次验证压缩效果(新增副本配置一致)
` `curl -I -H "Accept-Encoding: br" http://<external-ip>/static/app.js`
4. **配置热更新验证**`# 1. 修改ConfigMap(如调整缓存时长为7天)
kubectl edit configmap nginx-config
# 将max-age=2592000改为max-age=604800(7天)
# 2. 触发Deployment滚动更新(让配置生效)
kubectl rollout restart deployment nginx-deploy
# 预期输出:deployment.apps/nginx-deploy restarted
# 3. 验证更新效果
curl -I http://<external-ip>/static/app.js
` `# 预期响应头:Cache-Control: public, max-age=604800
⚠️ 避坑点:1. 配置热更新后必须重启Deployment,否则Pod不会加载新配置;2. 扩缩容时需同步调整资源限制,避免节点资源不足;3.负载均衡器健康检查路径需与Nginx配置一致,否则会误判服务不可用。
3.4 移动端与小程序场景:轻量化适配
移动端(iOS/Android)与小程序的核心诉求是低流量消耗+弱网适配------移动网络资费高、信号波动大,需在压缩率与解压缩性能间平衡(避免手机CPU过载),同时适配小程序的缓存机制限制(如微信小程序本地缓存上限100MB)。
3.4.1 移动端App场景(iOS/Android)
移动端压缩缓存需"端侧+服务端协同":服务端提供适配移动端的压缩格式,端侧实现本地缓存管理与解压缩优化。以下以Android(OkHttp)和iOS(Alamofire)为例,提供可复用代码。
1. 服务端适配配置(Nginx为例)
目标:识别移动端UA,返回轻量化压缩格式(避免Brotli高压缩率导致端侧解压缩耗时)。
http {
# 识别移动端UA
map $http_user_agent $is_mobile {
default 0;
~*Mobile|Android|iPhone|iPad 1;
}
# 移动端压缩配置(gzip优先,解压缩更快)
server {
listen 80;
server_name api.your-app.com;
if ($is_mobile = 1) {
gzip on;
gzip_comp_level 5; # 降低压缩级别,平衡流量与解压缩速度
gzip_types application/json application/xml; # 适配接口数据压缩
brotli off; # 关闭Brotli,避免移动端CPU过载
}
# 移动端接口缓存配置(短缓存,避免数据过时)
location /api/ {
proxy_pass http://backend;
if ($is_mobile = 1) {
add_header Cache-Control "private, max-age=60"; # 1分钟缓存
add_header ETag ""; # 关闭ETag,减少端侧计算
add_header Last-Modified $date_gmt; # 用修改时间做协商缓存
}
}
}
}
2. 端侧实现(Android/OkHttp)
核心:通过OkHttp拦截器实现解压缩与本地缓存,适配Android不同版本(Android 10+支持Brotli解压缩)。
java
// 1. 依赖引入(build.gradle)
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
implementation 'com.squareup.okhttp3:okhttp-brotli:4.12.0' // Brotli解压缩依赖
// 2. 自定义缓存拦截器(本地缓存管理)
public class MobileCacheInterceptor implements Interceptor {
private final Cache cache;
public MobileCacheInterceptor(Context context) {
// 配置本地缓存:10MB上限,避免占用过多手机存储
File cacheDir = new File(context.getCacheDir(), "http_cache");
cache = new Cache(cacheDir, 10 * 1024 * 1024);
}
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
String url = request.url().toString();
// 1. 优先从本地缓存获取(弱网时生效)
Cache.Response cacheResponse = cache.get(request);
if (cacheResponse != null && isWeakNetwork(context)) {
return cacheResponse.response();
}
// 2. 网络请求,添加压缩请求头
Request compressedRequest = request.newBuilder()
.header("Accept-Encoding", "gzip") // 移动端优先gzip
.build();
// 3. 响应处理,存入缓存
Response response = chain.proceed(compressedRequest);
if (response.isSuccessful()) {
// 仅缓存GET请求,避免POST数据缓存
if (request.method().equals("GET")) {
cache.put(compressedRequest, new Cache.Request(compressedRequest), response);
}
}
return response;
}
// 弱网判断(可根据实际需求调整)
private boolean isWeakNetwork(Context context) {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = cm.getActiveNetworkInfo();
return info != null && info.getType() == ConnectivityManager.TYPE_MOBILE && info.getSubtype() < TelephonyManager.NETWORK_TYPE_4G;
}
}
// 3. 初始化OkHttp客户端
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new MobileCacheInterceptor(this))
.addNetworkInterceptor(new GzipRequestInterceptor()) // 自动解压缩
.build();
3. iOS端实现(Alamofire)
Swift
import Alamofire
// 1. 自定义缓存策略
class MobileCachePolicy: NSObject, URLCacheDelegate {
let cache = URLCache(memoryCapacity: 5 * 1024 * 1024, diskCapacity: 10 * 1024 * 1024, diskPath: "mobile_cache")
func urlCache(_ cache: URLCache, cachedResponseFor request: URLRequest) -> CachedURLResponse? {
// 弱网时优先返回缓存
if isWeakNetwork() {
return cache.cachedResponse(for: request)
}
return nil
}
// 弱网判断
private func isWeakNetwork() -> Bool {
let reachability = try! Reachability()
return reachability.connection == .cellular && reachability.celluarType != .lte
}
}
// 2. 初始化Alamofire会话
let cachePolicy = MobileCachePolicy()
let configuration = URLSessionConfiguration.default
configuration.urlCache = cachePolicy.cache
configuration.requestCachePolicy = .useProtocolCachePolicy
configuration.httpAdditionalHeaders = [
"Accept-Encoding": "gzip" // 移动端优先gzip
]
let session = Session(configuration: configuration)
// 3. 发起请求
session.request("https://api.your-app.com/user", method: .get)
.responseJSON { response in
// 处理响应
print(response)
}
4. 验证方案
-
压缩验证 :通过Charles抓包,查看移动端请求的响应头是否为
Content-Encoding: gzip。 -
弱网验证:在手机开发者选项中开启"弱网模式"(如3G),观察App是否能快速加载缓存数据。
-
性能验证:通过Android Profiler或iOS Instruments,监控解压缩时的CPU占用(确保不超过50%)。
3.4.2 小程序场景(微信/支付宝)
小程序的核心限制:本地缓存上限100MB 、不支持Brotli解压缩 (部分平台)、域名必须备案。需结合小程序原生缓存API与服务端适配。
1. 服务端适配(以微信小程序为例)
server {
listen 443 ssl;
server_name mp.your-domain.com;
# 微信小程序UA识别
map $http_user_agent $is_mini_program {
default 0;
~*MicroMessenger/[0-9]+\.[0-9]+.*MiniProgram 1;
}
# 小程序压缩配置(仅gzip)
if ($is_mini_program = 1) {
gzip on;
gzip_comp_level 5;
gzip_types text/html application/javascript application/json;
brotli off;
}
# 小程序页面缓存(适配小程序包体积限制)
location /mini-program/ {
root /usr/share/nginx/html;
if ($is_mini_program = 1) {
add_header Cache-Control "public, max-age=86400"; # 1天缓存
add_header "Access-Control-Allow-Origin" "https://servicewechat.com"; # 跨域适配
}
}
}
2. 小程序端实现(微信小程序·JavaScript)
核心:使用wx.getStorageSync管理本地缓存,结合wx.request的压缩配置。
javascript
// 1. 封装请求工具(带缓存与压缩)
function requestWithCache(options) {
const { url, method = 'GET', data, cacheKey, cacheTime = 60 } = options;
const now = Date.now();
// 1. 读取本地缓存
const cacheData = wx.getStorageSync(cacheKey);
if (cacheData && (now - cacheData.timestamp) / 1000 <= cacheTime) {
return Promise.resolve(cacheData.data);
}
// 2. 发起网络请求(指定gzip压缩)
return new Promise((resolve, reject) => {
wx.request({
url,
method,
data,
header: {
'Accept-Encoding': 'gzip',
'Content-Type': 'application/json'
},
success: (res) => {
// 3. 存入本地缓存(避免超过100MB上限)
if (method === 'GET' && cacheKey) {
// 检查缓存占用,超过90MB清理旧缓存
wx.getStorageInfo({
success: (info) => {
if (info.currentSize > 90) {
wx.clearStorageSync();
}
wx.setStorageSync(cacheKey, {
data: res.data,
timestamp: now
});
}
});
}
resolve(res.data);
},
fail: (err) => {
reject(err);
}
});
});
}
// 2. 调用示例(获取商品列表)
requestWithCache({
url: 'https://mp.your-domain.com/mini-program/api/goods',
method: 'GET',
cacheKey: 'goods_list',
cacheTime: 300 // 5分钟缓存
}).then(data => {
console.log('商品列表', data);
}).catch(err => {
console.error('请求失败', err);
});
// 3. 图片缓存适配(小程序原生缓存)
wx.getImageInfo({
src: 'https://mp.your-domain.com/mini-program/img/goods.jpg',
success: (res) => {
// 图片已存入小程序缓存,下次加载直接复用
console.log('图片缓存路径', res.path);
}
});
3. 验证方案
-
缓存验证:在微信开发者工具中,通过"Storage"面板查看缓存数据是否存在,过期后是否自动更新。
-
压缩验证 :通过"Network"面板,查看请求的"Response Headers"是否包含
Content-Encoding: gzip。 -
缓存上限验证:循环存储缓存数据至100MB,观察是否触发自动清理(或小程序是否提示"缓存已满")。
3.5 物联网(IoT)终端场景:极致轻量化
物联网终端(如智能手环、智能家居控制器)的核心诉求是超低资源占用------终端硬件配置低(CPU主频常低于1GHz,内存不足128MB)、多为NB-IoT/LoRa等低带宽网络,需采用"极简压缩+无状态缓存"方案。
3.5.1 核心适配原则
-
压缩算法:选轻量化gzip(弃用Brotli)------Brotli解压缩需占用更多内存,物联网终端无法支撑。
-
数据格式:用JSON轻量化或Protocol Buffers------Protocol Buffers体积比JSON小30%+,且解析更快。
-
缓存策略:终端侧无本地缓存,依赖网关缓存------避免终端存储占用,由边缘网关统一管理缓存。
3.5.2 网关配置(Nginx+边缘网关)
边缘网关作为物联网终端与云端的中间层,承担压缩与缓存核心职责。以下为Nginx边缘网关配置:
http {
# 物联网终端UA识别(以智能手环为例)
map $http_user_agent $is_iot {
default 0;
~*IoT|SmartBand|Device 1;
}
server {
listen 80;
server_name gateway.iot-domain.com;
# IoT压缩配置(极简gzip)
if ($is_iot = 1) {
gzip on;
gzip_comp_level 3; # 极低压缩级别,优先保证解析速度
gzip_types application/json application/x-protobuf; # 适配PB格式
gzip_min_length 64; # 小数据也压缩(IoT数据多为短报文)
}
# IoT网关缓存(长缓存,终端无本地缓存)
location /iot/data/ {
proxy_pass http://cloud-server;
if ($is_iot = 1) {
add_header Cache-Control "public, max-age=3600"; # 1小时缓存
proxy_cache iot_cache; # 网关缓存
proxy_cache_valid 200 3600s; # 200响应缓存1小时
proxy_cache_bypass $arg_refresh; # 带refresh参数跳过缓存
}
}
# 缓存配置
proxy_cache_path /var/nginx/iot_cache levels=1:2 keys_zone=iot_cache:10m max_size=100m;
}
}
3.5.3 终端侧实现(C语言为例)
物联网终端多采用C语言开发,需使用轻量化gzip库(如zlib)实现解压缩,避免引入复杂依赖。
cs
#include <zlib.h>
#include <stdio.h>
#include <stdlib.h>
// 轻量化gzip解压缩函数(适配IoT终端)
int gzip_decompress(const unsigned char *compressed_data, int compressed_len,
unsigned char *uncompressed_data, int *uncompressed_len) {
z_stream stream;
int ret;
// 初始化zlib流
stream.zalloc = Z_NULL;
stream.zfree = Z_NULL;
stream.opaque = Z_NULL;
stream.avail_in = compressed_len;
stream.next_in = compressed_data;
stream.avail_out = *uncompressed_len;
stream.next_out = uncompressed_data;
// 初始化解压缩(gzip格式)
ret = inflateInit2(&stream, 16 + MAX_WBITS);
if (ret != Z_OK) return ret;
// 执行解压缩
do {
ret = inflate(&stream, Z_NO_FLUSH);
if (ret == Z_STREAM_ERROR) return ret;
switch (ret) {
case Z_NEED_DICT: ret = Z_DATA_ERROR;
case Z_DATA_ERROR:
case Z_MEM_ERROR:
inflateEnd(&stream);
return ret;
}
stream.avail_out -= stream.total_out;
stream.next_out += stream.total_out;
stream.total_out = 0;
} while (ret != Z_STREAM_END);
// 释放资源
inflateEnd(&stream);
*uncompressed_len = stream.total_out;
return Z_OK;
}
// 终端请求示例(简化)
void iot_request() {
// 1. 向边缘网关发起请求(带压缩头)
unsigned char request[] = "GET /iot/data/temp HTTP/1.1\r\n"
"Host: gateway.iot-domain.com\r\n"
"Accept-Encoding: gzip\r\n\r\n";
send_request(request, sizeof(request));
// 2. 接收压缩响应
unsigned char compressed_data[1024];
int compressed_len = receive_response(compressed_data, sizeof(compressed_data));
// 3. 解压缩响应
unsigned char uncompressed_data[4096];
int uncompressed_len = sizeof(uncompressed_data);
int ret = gzip_decompress(compressed_data, compressed_len, uncompressed_data, &uncompressed_len);
if (ret == Z_OK) {
printf("解压缩后数据:%.*s\n", uncompressed_len, uncompressed_data);
} else {
printf("解压缩失败:%d\n", ret);
}
}
3.5.4 验证方案
-
资源占用验证:通过终端调试工具(如J-Link)监控解压缩时的CPU占用(需≤30%)和内存使用(需≤10MB)。
-
网络流量验证:通过Wireshark抓包,对比压缩前后的报文大小(预期压缩率≥50%)。
-
缓存验证 :向网关发送两次相同请求,第二次查看网关日志是否显示
proxy_cache_hit。
3.6 场景适配总结:一张表搞定全场景选择
为方便快速选型,以下汇总各场景的核心配置要点,可直接对照使用:
| 场景 | 推荐压缩算法 | 压缩级别 | 缓存时长 | 核心避坑点 |
|---|---|---|---|---|
| Nginx/Apache | Brotli+gzip(双算法) | Brotli 11,gzip 6 | 静态30天,动态1分钟 | 版本号内嵌,避免URL参数 |
| 阿里云/腾讯云CDN | Brotli优先 | Brotli 11(阿里云)/9(腾讯云) | 静态30天,首页10分钟 | 图片不二次压缩,忽略用户参数 |
| K8s容器 | Brotli+gzip | 同Web服务器 | 同Web服务器 | ConfigMap管理配置,资源限制适配压缩 |
| 移动端App | gzip | gzip 5 | 接口1分钟,静态资源1天 | 关闭Brotli,避免CPU过载 |
| 小程序 | gzip | gzip 5 | 1天,不超过100MB | 跨域适配,定期清理缓存 |
| 物联网终端 | gzip | gzip 3 | 网关1小时,终端无缓存 | 用PB格式,轻量化解压缩库 |
至此,全场景压缩与缓存的落地方案已覆盖完成。实际应用中,需根据场景流量、终端性能、业务需求动态调整配置,建议结合监控工具(如Prometheus+Grafana)跟踪压缩率、缓存命中率等核心指标,持续优化。