在 nginx 中绕过缓存的核心做法是利用 map 指令将包含特定 cookie 值的请求映射为不缓存的标记,并在 proxy_cache_bypass 中引用该标记。具体操作是定义一个变量(如 $no_cache),通过正则匹配 $http_cookie 来设置其值,随后在 location 块中配置 proxy_cache_bypass $no_cache,这样当条件满足时,nginx 会直接向后端发起请求并跳过本地缓存。

如何配置 map 指令以识别特定的 Cookie 值
要实现这一功能,必须在 http 上下文中使用 map 指令创建一个新变量。该指令接收两个参数:源变量(通常是 $http_cookie)和默认返回值。通过编写正则表达式,可以精确匹配目标 Cookie 的存在与否。例如,若希望当 Cookie 名为 session_id 且值为 admin 时触发绕过逻辑,需确保正则能捕获该键值对,并将结果赋给控制缓存行为的变量。

http {
# 定义变量 $bypass_cache,默认为 "0"
# 如果 cookie 中包含 session_id=admin,则设为 "1"
map $http_cookie $bypass_cache {
default 0;
~*session_id=admin 1;
}
server {
listen 80;
server_name example.com;
location /api/ {
proxy_pass http://backend_servers;
# 启用缓存
proxy_cache my_cache;
# 当 $bypass_cache 为 1 时,不使用缓存
proxy_cache_bypass $bypass_cache;
# 同时设置响应头,防止浏览器缓存
add_header Cache-Control "no-cache, no-store, must-revalidate";
}
}
}
上述代码展示了完整的配置结构。首先,map 块定义了匹配规则,~* 表示不区分大小写的正则匹配。当请求携带 session_id=admin 时,$bypass_cache 变为 1。接着,在 location 中,proxy_cache_bypass 指令检查该变量,若为非零非空字符串,Nginx 将直接转发请求至后端,并将后端返回的内容作为未缓存的响应发送。此外,添加 Cache-Control 头是为了确保客户端浏览器也不会缓存这些敏感数据。
如何处理多个不同条件的 Cookie 绕过策略
当业务需要针对多种不同的 Cookie 值执行不同的缓存策略时,可以在同一个 map 指令中扩展匹配规则。Nginx 会按顺序评估这些规则,一旦匹配成功即停止后续匹配。这种机制允许在一个集中位置管理所有绕过逻辑,避免在多个 location 块中重复配置。对于复杂的组合条件,可以使用更精细的正则表达式或结合其他变量进行判断。

http {
map $http_cookie $bypass_cache {
default 0;
# 条件1: 管理员登录状态
~*user_role=admin 1;
# 条件2: 调试模式开启
~*debug=true 1;
# 条件3: 特定会话ID
~*session_id=abc123 1;
}
server {
listen 80;
server_name example.com;
location /dynamic/ {
proxy_pass http://backend_dynamic;
proxy_cache dynamic_cache;
proxy_cache_bypass $bypass_cache;
}
}
}
在这个扩展示例中,map 指令包含了三个独立的匹配项。只要请求中的 Cookie 符合其中任意一项(如 user_role=admin 或 debug=true),$bypass_cache 就会被设置为 1。这种写法保持了配置的整洁性,便于维护。需要注意的是,正则表达式的顺序很重要,如果有重叠的情况,靠前的规则优先生效。同时,确保后端服务能够正确处理这些绕过缓存的请求,通常意味着后端应返回最新的动态数据。
当 Cookie 值包含特殊字符或 URL 编码时如何正确匹配
在实际应用中,Cookie 的值可能经过 URL 编码,或者包含空格、特殊符号等字符,这会导致简单的正则匹配失败。例如,如果 session_id 的值是 abc def,它在 HTTP 头中可能会显示为 abc%20def。此时,直接使用 ~*session_id=abc def 将无法匹配。解决方法是使用通配符或转义序列来处理这些情况,或者在匹配时忽略编码后的格式,仅关注关键标识。
# 处理包含空格或特殊字符的 Cookie 值
map $http_cookie $bypass_cache {
default 0;
# 匹配 session_id 后跟任意字符直到分号或结尾
~*session_id=[^;]+ 1;
}
上述代码使用了 [^;]+ 来匹配 session_id= 之后的所有内容,直到遇到下一个 Cookie 的分号分隔符。这种方法更加健壮,能够适应各种编码形式和特殊字符。它不关心具体的值是什么,只关心是否存在该 Cookie 键。如果业务逻辑需要验证具体的值,可能需要先对 $http_cookie 进行解码,但这在 Nginx 原生配置中较为复杂,通常建议在后端处理或确保前端发送的是标准编码格式。通过这种方式,可以有效避免因格式问题导致的缓存绕过失效。


















