Nginx的upstream模块不支持同时启用ip_hash和weight;因ip_hash要求确定性映射,而weight依赖概率分发,二者逻辑冲突;可通过分阶段策略、hash $cookie_jsessionid一致性哈希或map条件路由实现会话粘性与权重兼顾。

Nginx 的 `upstream` 模块本身**不支持同时启用 `ip_hash` 和 `weight`**。这是关键前提——`ip_hash` 是静态会话绑定的刚需解法,但它的设计逻辑与权重调度存在根本冲突:哈希要求确定性映射(同一 IP 总打同一台),而权重轮询依赖概率性分发(按比例分配请求)。二者无法共存于同一个 upstream 块中。 不过,业务连续性需求真实存在,尤其在 Session 未共享、又需兼顾服务器能力差异的场景下,有几种务实可行的路径:
明确区分:ip_hash 用于会话稳定,权重用于扩容过渡期
若集群中既有老服务器(性能弱、需少承接流量),又有新服务器(性能强、需多承接),但又必须保持会话粘性,可采用“分阶段策略”:
- 先用 ip_hash 确保所有现有用户始终落在原服务器上,避免登出或状态丢失;
- 在新增节点时,**不直接加入当前 ip_hash upstream**,而是单独配置一个带权重的新 upstream(如
backend_new),配合业务灰度路由(例如通过请求头、URL 路径或 Cookie 标识)将部分新用户导流过去; - 待老用户自然减少、Session 过期后,再整体切换至新集群,并启用新的 ip_hash 配置。
替代方案:用 hash $cookie_jsessionid 实现应用层会话亲和
当后端应用(如 Java Tomcat、Spring Boot)已生成带签名的 session ID Cookie(如 JSESSIONID),可用通用哈希代替 ip_hash:
- 配置
hash $cookie_jsessionid consistent;—— 一致性哈希能缓解节点增减导致的会话大规模迁移; - 该方式天然兼容权重:
server 192.168.1.10:8080 weight=3;等仍有效; - 前提是客户端已携带有效 session Cookie,首次请求可能需配合其他策略(如 fallback 到 least_conn)。
进阶控制:结合 map 指令做条件化哈希路由
对特定 IP 段或 User-Agent,可动态决定是否启用哈希或权重分配:
- 用
map提取客户端特征(如$remote_addr或自定义 header),生成变量$route_mode; - 在
location中根据$route_mode选择不同 upstream:一个走ip_hash(面向内网/固定用户),另一个走加权轮询(面向公网/临时流量); - 这种分流不破坏任一算法的语义,也便于灰度验证和故障隔离。
必须避开的误区
以下配置是无效且会被 Nginx 拒绝的:
-
upstream backend { ip_hash; server a weight=2; server b weight=1; }→ 启动失败,报错 “ip_hash cannot be used with weight”; - 试图用
hash $remote_addr weight=2替代 —— Nginx 不支持 hash 指令带 weight 参数; - 仅靠增加 max_fails/fail_timeout 来“模拟权重” —— 这属于健康检查范畴,不影响正常状态下的调度倾向。











