加群联系作者vx:xiaoda0423
仓库地址:https://webvueblog.github.io/JavaPlusDoc/
https://1024bat.cn/
🚀 一、前后端缓存策略协同
🔧 1. 前端:合理利用浏览器缓存
强缓存(from disk cache / memory cache)
-
浏览器命中强缓存,不发请求,直接用本地缓存
适合不常改动的静态资源:如图片、字体、JS/CSS 等
服务端响应:
Cache-Control: public, max-age=86400 Expires: Wed, 16 Apr 2025 12:00:00 GMT
前端表现:
协商缓存(304)
-
服务端响应:
Last-Modified: Wed, 10 Apr 2025 06:00:00 GMT ETag: "abc123xyz"
客户端下一次发起请求带上:
If-Modified-Since: ... If-None-Match: ...
如果资源没变,返回 304,节省带宽;否则返回新的 200
强制刷新(Ctrl+F5)
-
浏览器自动加上请求头:
Cache-Control: no-cache Pragma: no-cache
🧠 2. 后端:根据资源类型设置缓存响应头
建议结合 Nginx、Spring Boot 或其他后端框架统一配置静态资源策略。
✅ 示例策略(Nginx):
location ~* .(js|css|png|jpg|jpeg|gif|woff|woff2|svg|ico)$ {
expires 30d;
add_header Cache-Control "public, max-age=2592000, immutable";
}
location /api/ {
expires off;
add_header Cache-Control "no-store";
}
✅ 示例策略(Spring Boot):
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**")
.addResourceLocations("classpath:/static/")
.setCacheControl(CacheControl.maxAge(30, TimeUnit.DAYS).cachePublic());
}
}
🎯 二、配合思路
资源类型 |
建议缓存策略 |
原因/说明 |
---|---|---|
JS/CSS |
Cache-Control: max-age=31536000, immutable |
不常更新、版本号改名 |
图片/字体 |
Cache-Control: max-age=31536000, immutable |
不变就一直缓存 |
HTML |
Cache-Control: no-cache |
每次都需要检查是否有更新 |
API 请求 |
Cache-Control: no-store |
避免缓存敏感数据,实时性强 |
JSON 配置文件 |
可选协商缓存 (ETag + Last-Modified) |
若更新频率低可协商缓存 |
上传文件 |
通常不缓存 |
私密/敏感性资源 |
🎨 三、结合构建工具版本号策略(前端重点)
💡 原理:
每次构建时,资源文件自动添加 hash 值(如 app.7ad32f.js
),强缓存时间可以设置很长(如一年),资源更新后文件名变了,用户自然请求最新资源。
Webpack/Vite/Rollup 常用方式:
output: {
filename: '[name].[contenthash].js'
}
HTML 引用时自动更新引用路径,如:
<script src="/static/js/app.7ad32f.js"></script>
🛠 四、注意点
ETag 在集群部署时建议关闭
每个节点生成的 ETag 可能不同,导致命中失败 →
nginx.conf
:etag off;
尽量不要前端禁用缓存(Disable Cache)
-
除了调试开发,正式环境打开会极大增加流量
图片字体类资源 CDN 分发 + 永久缓存
-
甚至可以设置:
Cache-Control: max-age=315360000, immutable
动态数据慎用缓存头
-
比如用户信息、购物车、支付状态,不建议缓存
前端合理配置构建和版本策略,后端精细控制缓存响应头。
层级
优化手段
前端
hash 文件名、immutable 标记、避免 no-cache 滥用
后端
静态资源加长缓存、动态资源配合校验、关闭 ETag(如必要)
网络
启用 CDN 缓存、压缩 Gzip/Brotli、减少 RTT
业务
尽量数据解耦(静态 vs 动态),结构分离、更新原子性
准备 3 个 Nginx 实例:模拟多层代理(Client → Proxy1 → Proxy2 → Backend)
配置测试页面:
后端 Nginx 返回
$remote_addr
,$http_x_forwarded_for
,$http_x_real_ip
来验证 IP 透传。同时返回
$request_method
,$request_uri
来验证proxy_pass
和rewrite
效果。添加资源带上
ETag
,Last-Modified
,Cache-Control
头部测试缓存策略。
Curl 测试命令模板:
curl -I -H "Cache-Control: no-cache" http://localhost/static.js curl -I -H "If-None-Match: "etag123"" http://localhost/static.js curl -I -H "a_b: 123" http://localhost:81
关键配置测试点:
-
proxy_pass
+ URI 规则的差异行为rewrite + break
对proxy_pass
行为影响proxy_set_header
的 header 继承与覆盖机制underscores_in_headers
开关对 header 变量命名的影响缓存命中(304 vs 200 vs from disk cache)
✅ 一、蓝绿部署(Blue-Green Deployment)
🔍 核心思路:
同时部署两个版本:
blue
:当前稳定线上版本green
:即将上线的新版本
通过 Nginx 实现快速流量切换,避免停机。
🔧 Nginx 配置方法(蓝绿环境切换):
upstream app_backend { server 10.0.0.1:8080; # blue # server 10.0.0.2:8080; # green(上线时把这行打开,把上面注释掉) } server { listen 80; location / { proxy_pass http://app_backend; } }
🔁 切换版本时:只需修改
upstream
的目标 IP 并 reload Nginx,即可完成无缝蓝绿切换。
✨ 实操建议:
配合 Jenkins/脚本做一键切流
结合 health check,避免新版本服务不可用
✅ 二、灰度发布(Canary Release)
🔍 核心思路:
只让部分用户使用新版本,根据规则(如 IP、cookie、header、比例等)灰度流量。
🎯 场景一:按 IP 灰度发布
map $remote_addr $gray_user { default 0; 192.168.1.100 1; # 指定用户 IP 灰度 } upstream app_v1 { server 10.0.0.1:8080; # 旧版本 } upstream app_v2 { server 10.0.0.2:8080; # 新版本 } server { listen 80; location / { if ($gray_user = 1) { proxy_pass http://app_v2; } proxy_pass http://app_v1; } }
🎯 场景二:按 Cookie 灰度发布
map $http_cookie $gray_cookie { default 0; "~*gray_user=true" 1; } location / { if ($gray_cookie = 1) { proxy_pass http://app_v2; } proxy_pass http://app_v1; }
🎯 场景三:按比例灰度发布(权重轮询)
upstream canary { server 10.0.0.1:8080 weight=9; # v1 - 90% server 10.0.0.2:8080 weight=1; # v2 - 10% } server { listen 80; location / { proxy_pass http://canary; } }
⚠️ 注意:这种方式对“同一个用户固定命中新旧版本”没有保证。
🔧 Nginx 配合蓝绿/灰度部署的实操小技巧:
功能点
技术方案
精准用户灰度
$remote_addr
/
$http_cookie
/$http_user_agent
动态权重切流
使用 nginx + consul/etcd + lua/openresty
实时切换 upstream
配合
nginx reload
ordynamic upstream
模块监控切流效果
配合
access_log
+ log_format 打日志分析健康检查
proxy_next_upstream
+
max_fails
+fail_timeout
✅ 项目结构(蓝绿灰度 Nginx 示例)
nginx-canary-demo/ ├── docker-compose.yml ├── nginx/ │ ├── nginx.conf │ └── conf.d/ │ └── default.conf ├── app-v1/ # 模拟蓝色版本 │ └── index.html ├── app-v2/ # 模拟绿色版本 │ └── index.html └── test/ └── curl_test.sh
📦 docker-compose.yml
version: '3.8' services: nginx: image: nginx:latest volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf - ./nginx/conf.d:/etc/nginx/conf.d - ./app-v1:/usr/share/nginx/html/v1 - ./app-v2:/usr/share/nginx/html/v2 ports: - "8080:80" app-v1: image: httpd:alpine volumes: - ./app-v1:/usr/local/apache2/htdocs/ ports: - "8081:80" app-v2: image: httpd:alpine volumes: - ./app-v2:/usr/local/apache2/htdocs/ ports: - "8082:80"
🧠 nginx/conf.d/default.conf
# 蓝绿灰度配置 map $http_cookie$is_gray_user { default 0; "~*gray_user=true" 1; } upstream blue { server app-v1:80; } upstream green { server app-v2:80; } server { listen 80; server_name localhost; location / { if ($is_gray_user = 1) { proxy_pass http://green; } proxy_pass http://blue; } }
🔧 nginx/nginx.conf
worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type text/html; sendfile on; keepalive_timeout 65; include /etc/nginx/conf.d/*.conf; }
📄 app-v1/index.html
<!DOCTYPE html> <html> <head><title>Blue Version</title></head> <body style="background-color:lightblue;"> <h1>Blue Version: v1</h1> </body> </html>
📄 app-v2/index.html
<!DOCTYPE html> <html> <head><title>Green Version</title></head> <body style="background-color:lightgreen;"> <h1>Green Version: v2 (灰度用户专属)</h1> </body> </html>
🧪 test/curl_test.sh
#!/bin/bash echo "== 普通用户访问 ==" curl -s http://localhost:8080 | grep h1 echo "== 灰度用户访问 ==" curl -s -H "Cookie: gray_user=true" http://localhost:8080 | grep h1
🚀 使用方法
启动项目:
docker-compose up --build
访问测试:
普通访问: http://localhost:8080
灰度访问:
curl -H "Cookie: gray_user=true" http://localhost:8080
运行测试脚本:
chmod +x test/curl_test.sh ./test/curl_test.sh
🧩 后续进阶建议
功能
方法
动态流量比例调整
Nginx + Lua + Redis 控制比例
权重灰度(10% 进入 green)
upstream weight
+ sticky session
请求路径/UA/Referer 灰度
用
$http_user_agent
或$request_uri
做 map🌈 场景回顾:蓝绿环境 + 灰度切流
Blue(当前稳定)
Green(新版本)
默认流量都走 Blue
Jenkins 按钮发布时,先检测 Green 健康,再流量切换
切流可灰度逐步调整、也可一键全量
🛠️ 1. Nginx 目标配置(动态切换 upstream)
我们通过软链接 + reload 实现:
bash 复制编辑 /etc/nginx/conf.d/default.conf -> points to: conf.d/blue.conf or conf.d/green.conf
例如:
conf.d/upstream-blue.conf
upstream backend { server app-v1:80; }
conf.d/upstream-green.conf
upstream backend { server app-v2:80; }
conf.d/location.conf
server { listen 80; location / { proxy_pass http://backend; } }
🧪 2. 健康检查脚本(
health_check.sh
)#!/bin/bash TARGET_URL=$1 RETRY=5 for i in $(seq 1 $RETRY); do echo"Health check [$i/$RETRY]: $TARGET_URL" code=$(curl -s -o /dev/null -w "%{http_code}""$TARGET_URL") if [ "$code" == "200" ]; then echo"✅ Health check success." exit 0 fi sleep 2 done echo"❌ Health check failed." exit 1
🚀 3. 一键切流脚本(
switch_traffic.sh
)#!/bin/bash TARGET=$1# blue or green NGINX_DIR="/etc/nginx/conf.d" LINK="$NGINX_DIR/default.conf" UPSTREAM="$NGINX_DIR/upstream-${TARGET}.conf" if [ "$TARGET" != "blue" ] && [ "$TARGET" != "green" ]; then echo"Usage: $0 [blue|green]" exit 1 fi # 健康检查 bash ./health_check.sh "http://127.0.0.1:808${TARGET/blue/1}${TARGET/green/2}" || exit 1 # 切换 upstream rm -f $LINK ln -s $UPSTREAM$LINK # Reload Nginx nginx -s reload echo"✅ 切流到 $TARGET 成功"
🧱 4. Jenkins 流程(自由风格任务 / Pipeline)
方式一:自由风格任务 + 参数
添加构建参数:
TARGET_ENV
(值为blue
或green
)构建步骤:
cd /your/nginx-deploy-dir git pull chmod +x switch_traffic.sh ./switch_traffic.sh $TARGET_ENV
方式二:Pipeline 示例
pipeline { agent any parameters { choice(name: 'TARGET', choices: ['blue', 'green'], description: '选择要切流的版本') } stages { stage('切流') { steps { sh ''' cd /your/nginx-deploy-dir git pull ./switch_traffic.sh $TARGET ''' } } } }
🔒 稳定性保证(建议搭配)
功能
技术点
健康检查
curl + retry
灰度切换(10%)
Nginx map + $request_id hash 灰度
回滚
切换软链接回 blue 即可
实时监控
Prometheus + Grafana
异常自动报警
Jenkins 配合 DingTalk/飞书
Nginx 的主配置文件(nginx.conf)
🔧
worker_processes 1;
启动 1 个 worker 进程(处理请求的核心进程)
通常设为
auto
(自动根据 CPU 核心数来分配)
⚙️
events { worker_connections 1024; }
这是 事件模块,控制每个 worker 能同时处理的连接数:
worker_connections 1024
:一个 worker 最多能处理 1024 个并发连接理论最大并发:
worker_processes × worker_connections
(但受限于系统 ulimit)
🌐
http { ... }
Nginx 的 HTTP 服务核心配置块,包含所有 web server 配置。
逐条解释:
📎
include mime.types;
引入
mime.types
文件,告诉 Nginx 各种文件扩展名对应的Content-Type
(如.html
是text/html
)
📎
default_type text/html;
如果找不到合适的 mime type,就默认使用
text/html
🚀
sendfile on;
开启零拷贝(zero copy),优化文件传输效率
用于静态资源场景(图片、视频、压缩包等)
🔁
keepalive_timeout 65;
TCP keep-alive 时间,单位:秒
如果 65 秒内没有请求,则断开连接,节省资源
默认值是
75
,这里调成65
说明略早释放
📁
include /etc/nginx/conf.d/*.conf;
引入所有
/etc/nginx/conf.d/
目录下的.conf
文件所有的
server {}
或location {}
块通常写在这里
例子:
/etc/nginx/ ├── nginx.conf # 主配置 └── conf.d/ ├── app1.conf # 站点1 ├── app2.conf # 站点2
📁 项目结构建议
deploy/ ├── nginx/ │ ├── blue.conf # 蓝环境配置 │ ├── green.conf # 绿环境配置 │ └── main.conf # 入口 nginx 配置 (引用 upstream) ├── scripts/ │ └── switch_env.sh # 切流脚本(蓝 -> 绿 / 绿 -> 蓝)
🧩
main.conf
(Nginx 主配置引用 upstream)# main.conf (加载到 nginx.conf 或 conf.d/default.conf) upstream backend { include /etc/nginx/upstream/active.conf; } server { listen 80; location / { proxy_pass http://backend; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location = /healthz { return 200 'ok'; } }
🟦
blue.conf
# blue.conf server 10.0.0.11:8080 max_fails=3 fail_timeout=30s;
🟩
green.conf
# green.conf server 10.0.0.12:8080 max_fails=3 fail_timeout=30s;
🔗
active.conf
(软链接)# 初始环境为 blue ln -s /etc/nginx/upstream/blue.conf /etc/nginx/upstream/active.conf
🛠️
switch_env.sh
(脚本实现一键切流)#!/bin/bash UPSTREAM_DIR="/etc/nginx/upstream" CURRENT=$(readlink "$UPSTREAM_DIR/active.conf") if [[ $CURRENT == *"blue.conf" ]]; then NEW_TARGET="green.conf" else NEW_TARGET="blue.conf" fi echo"[INFO] 切换到环境: $NEW_TARGET" # 更新软链接 ln -sf "$UPSTREAM_DIR/$NEW_TARGET""$UPSTREAM_DIR/active.conf" # 检查健康 echo"[INFO] 进行健康检查..." CHECK_URL="http://127.0.0.1/healthz" sleep 1 HEALTH=$(curl -s --max-time 3 "$CHECK_URL") if [[ "$HEALTH" == "ok" ]]; then echo"[INFO] 健康检查通过,重载 Nginx..." nginx -s reload echo"[OK] 切流成功!当前环境:$NEW_TARGET" else echo"[ERROR] 健康检查失败,回滚..." # 回滚 ln -sf "$CURRENT""$UPSTREAM_DIR/active.conf" nginx -s reload echo"[ROLLBACK] 已回滚至 $CURRENT" exit 1 fi
✅ 使用方式
# Jenkins中执行 bash /path/to/scripts/switch_env.sh
💡 可选增强点
功能
建议方式
自动灰度比例切换
Nginx
weight
参数 + hash多版本健康检查
/healthz
带版本参数
压力测试
wrk
/
ab
/hey
工具可视化状态切换
搭配
Nginx status + Lua