老板突然发问 公司OA系统突然无法登录 我慌了

797 阅读4分钟

前言

有一天,老板突然登录后台管理系统,说系统卡住了,无法登录,让我马上和运维排查问题

从点击登录到卡住,返回请求错误码足足等待了超过30S,老板挂面,我可能有被裁风险

image.png

排查问题

点击登录以后,前端请求后端的接口,这里的流程是前端通过跨域请求实现的。 方式是通过 nginx 服务器代理请求后端的接口的。

我们定位到 nginx 处理跨域请求的时候的配置上。

Nginx 在使用 proxy_pass 进行域名代理时,可能会出现缓存问题,导致后端服务更新后客户端无法及时获取最新内容。这通常由多种因素引起,包括 Nginx 自身缓存、上游服务器缓存头设置或浏览器缓存策略等诸多因素,我们一个个进行排查

一,确认缓存的来源

在解决问题前,需先确定缓存位置:

  1. 浏览器缓存:通过开发者工具(如 Chrome 的 Network 面板)检查响应头中的 Cache-Control 和 Expires
  2. Nginx 代理缓存:检查 Nginx 配置是否启用了 proxy_cache 或相关指令。
  3. 上游服务器缓存:检查后端应用是否设置了缓存头。

很容易我们就排除了浏览器的缓存和上游服务器后端的缓存,前端浏览器这边 Cache-Control Expires 已经设置好响应头,同时后端应用也设置好了缓存头

接下来我们将问题定位到运维的位置

二、禁用 Nginx 代理缓存

在处理跨域请求(CORS)时,Nginx 需要同时解决两个关键问题:跨域头配置禁用缓存。以下是针对这两个需求的配置方案:

一、基础配置:跨域头 + 禁用缓存

server {
    listen 80;
    server_name your-domain.com;
    
    # 处理跨域请求
    location /api/ {
        # 代理配置
        proxy_pass http://backend-api-server/;  # 后端 API 服务器地址
        
        # 跨域头配置
        add_header 'Access-Control-Allow-Origin' '*' always;
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
        add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization' always;
        
        # 允许携带凭证(如 cookies)
        add_header 'Access-Control-Allow-Credentials' 'true' always;
        
        # OPTIONS 请求直接返回 204
        if ($request_method = 'OPTIONS') {
            return 204;
        }
        
        # 禁用缓存配置
        proxy_no_cache $cookie_nocache $arg_nocache $arg_comment;
        proxy_cache_bypass $cookie_nocache $arg_nocache $arg_comment;
        
        add_header Cache-Control "no-cache, no-store, must-revalidate" always;
        add_header Pragma "no-cache" always;
        add_header Expires "0" always;
        
        # 其他代理常用配置
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

二、高级配置:针对不同请求类型优化

1. 静态资源与动态 API 差异化处理
server {
    # 静态资源(允许缓存)
    location /static/ {
        proxy_pass http://backend-static/;
        # 默认缓存策略(根据需要调整)
        expires 7d;
    }
    
    # API 请求(禁用缓存)
    location /api/ {
        proxy_pass http://backend-api/;
        
        # 跨域头
        add_header 'Access-Control-Allow-Origin' '*' always;
        # ... 其他 CORS 头
        
        # 禁用缓存
        proxy_no_cache 1;
        proxy_cache_bypass 1;
        add_header Cache-Control "no-cache, no-store, must-revalidate" always;
        add_header Pragma "no-cache" always;
        add_header Expires "0" always;
    }
}
2. 仅对特定 API 禁用缓存
location /api/no-cache/ {
    proxy_pass http://backend/;
    
    # 禁用缓存
    proxy_no_cache $arg_nocache;
    proxy_cache_bypass $arg_nocache;
    
    # 动态添加 nocache 参数来控制是否缓存
    # 例如:/api/no-cache/data?nocache=1
}
3. 针对常用写死的域名,让每次请求都进行 DNS 查询

企业微信截图_17514472935097.png

http {
    resolver 8.8.8.8 valid=10s;

    server {
        listen 80;

        location / {
            set $upstream_host a.b.com;
            proxy_pass https://$upstream_host;
            proxy_set_header Host $upstream_host;
        }
    }
}

三、验证配置是否生效

1. 检查响应头
curl -I http://your-domain.com/api/data

# 预期输出:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE
Access-Control-Allow-Headers: DNT,X-Mx-ReqToken,...
Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: 0
2. 浏览器开发者工具验证

在 Chrome/Firefox 中:

  1. 打开开发者工具 → Network 面板
  2. 发送请求并检查响应头
  3. 确认没有 (from cache) 标记

通过以上配置,可确保 Nginx 在处理跨域请求时正确禁用缓存,同时满足 CORS 安全要求。根据具体业务需求调整配置细节,平衡性能与安全性。

三、 常见问题与解决方案

缓存仍未完全禁用

  • 问题原因

    • 上游服务器设置了缓存头,覆盖了 Nginx 的配置
    • CDN 缓存未清除
    • 浏览器强缓存
  • 解决方案

    • 使用 proxy_ignore_headers Cache-Control Expires 忽略上游缓存头
    • 若使用 CDN,在 CDN 控制台刷新缓存
    • 要求用户使用 Ctrl+F5(Windows)或 Command+Shift+R(Mac)强制刷新

Nginx 配置生效部分

修改配置后需重启或重载 Nginx:

sudo nginx -s reload

总结

前端针对这种问题需要提前做预防措施,为了避免

预防措施

  1. 开发阶段
  • 使用代理服务器处理跨域(如 Vite 的 server.proxy
  • 在浏览器开发者工具中始终启用「Disable cache」
  1. 生产环境
  • 对静态资源使用版本化(如 app.js?v=1.0.1
  • 为 API 请求设置合理的缓存策略(如频繁更新的数据使用 no-cache
  • 定期审查服务器和 CDN 的缓存配置
解决方案总结
问题类型解决方案
跨域错误1. 修改服务器 Nginx 配置,添加正确的 CORS 头
2. 使用代理服务器(如 Vite/Webpack 代理)
3. 确保请求配置与服务器允许的范围一致
浏览器缓存1. 在开发者工具中禁用缓存
2. 添加响应头 Cache-Control: no-cache
3. 请求 URL 添加随机参数
服务器缓存1. 修改后端代码,禁用缓存头
2. 检查 Nginx 配置,确保正确设置 proxy_no_cache
CDN 缓存1. 在 CDN 控制台刷新缓存
2. 调整 CDN 缓存规则(如设置 Cache-Control: no-cache

至此完结