map指令仅做变量映射,不操作缓冲区;通过提取$uri等路径特征生成服务名、缓存策略等标签,再由proxy_cache、proxy_pass等指令协同实现动态分发与缓存控制。
map 指令本身不操作缓冲区,也不直接控制缓存行为;它只做变量映射。所谓“结合缓冲区实现路径动态分发”,本质是用 map 提取路径特征生成逻辑标签(如服务名、缓存策略、后端集群),再由 proxy_cache、proxy_pass 等指令协同完成流量分发与缓存控制。
从请求路径提取关键维度map 的输入必须是字符串型变量,$uri或$request_uri是最常用源。注意二者区别:$uri 是解码后、标准化的路径(不含查询参数),适合做精确路由;$request_uri 保留原始编码和参数,适合需透传完整路径的场景。
提取一级路径作为服务标识:
map $uri $service {~^/api/v1/users/ "users-v1";~^/api/v1/orders/ "orders-v1";~^/static/ "cdn-static";default "default-svc";}避免正则冲突:匹配顺序从上到下,长路径需放前面(如 /api/v1/users/ 要在 /api/v1/ 前),否则会被更宽泛规则截断不建议用 $request_uri 做缓存 key 主体——含参数易导致缓存碎片化;如需区分参数,应单独用 map 提取特定 arg(如 $arg_version)再组合用 map 驱动缓存策略与回源目标一个路径可能同时决定“去哪台后端”和“怎么缓存”。这两个决策可由不同 map 并行完成,再在 location 中组合使用:
定义缓存区域名:
map $uri $cache_zone {~^/static/ "static_zone";~^/api/v1/(users|orders)/ "api_v1_zone";default "no_cache_zone";}定义缓存 key 构造方式(影响命中率):map $uri $cache_key {~^/static/ "$host$uri";~^/api/v1/users/ "$host$uri$arg_user_id";default "$host$uri";}对应 upstream 必须提前声明,名称与 map 输出值严格一致:upstream users-v1 { server 10.0.2.10:8080; }upstream orders-v1 { server 10.0.2.11:8080; }在 location 中落地分发与缓存逻辑map 只生成变量,真正起作用的是后续指令。典型配置结构如下:启用缓存模块(需在 http 块中已定义 proxy_cache_path):proxy_cache $cache_zone;proxy_cache_key $cache_key;proxy_cache_valid 200 302 10m;动态转发到对应 upstream:proxy_pass http://$service;若需强制跳过缓存(如带特定 header 的调试请求),可用另一个 map 控制 proxy_cache_bypass:map $http_x_no_cache $cache_bypass { "1" "1"; default ""; }注意 proxy_pass 后不能加路径(如 http://$service/),否则会覆盖原始 URI;如需重写路径,用 rewrite 或 proxy_redirect常见问题与避坑点map 必须写在 http 块顶层,server 或 location 内无效$service 等变量输出值必须与 upstream 名完全一致,包括大小写和符号(支持下划线,不支持短横线)
正则匹配要加引号和 ~ 前缀,如 "~^/api/";不加 ~ 就是纯字符串匹配所有 map 必须设 default 分支,否则未匹配时变量为空,可能导致 502 或配置解析失败缓存 key 中慎用 $request_body —— 它在 proxy_pass 之后才可读,且仅对 POST/PUT 生效,容易引发 400 或缓存错乱
