Skip to content

IP Hash配置

IP Hash算法根据客户端IP地址分配请求,同一IP的请求总是分配到同一台服务器,实现会话保持。

基本配置

启用IP Hash

nginx
upstream backend {
    ip_hash;

    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    server 192.168.1.12:8080;
}

server {
    listen 80;
    server_name lb.example.com;

    location / {
        proxy_pass http://backend;
    }
}

工作原理

根据客户端IP进行哈希计算:

  • 客户端IP:192.168.1.100
  • 哈希值:hash(192.168.1.100)
  • 分配到:服务器A
  • 后续请求:始终分配到服务器A

完整配置

生产环境配置

nginx
upstream backend {
    ip_hash;

    server 192.168.1.10:8080 max_fails=3 fail_timeout=30s;
    server 192.168.1.11:8080 max_fails=3 fail_timeout=30s;
    server 192.168.1.12:8080 max_fails=3 fail_timeout=30s;
}

server {
    listen 80;
    server_name lb.example.com;

    access_log /var/log/nginx/lb.access.log;
    error_log /var/log/nginx/lb.error.log;

    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;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }
}

使用真实IP

考虑代理服务器

nginx
upstream backend {
    ip_hash;

    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    server 192.168.1.12:8080;
}

server {
    listen 80;
    server_name lb.example.com;

    location / {
        proxy_pass http://backend;

        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

使用X-Forwarded-For

nginx
map $http_x_forwarded_for $client_ip {
    default $remote_addr;
    ~^([0-9.]+) $1;
}

upstream backend {
    ip_hash;

    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    server 192.168.1.12:8080;
}

server {
    listen 80;
    server_name lb.example.com;

    location / {
        proxy_pass http://backend;

        proxy_set_header X-Real-IP $client_ip;
    }
}

适用场景

有状态应用

nginx
upstream backend {
    ip_hash;

    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
}

说明:

  • 需要保持会话状态
  • 用户登录状态
  • 购物车数据

WebSocket连接

nginx
upstream backend {
    ip_hash;

    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
}

server {
    listen 80;
    server_name ws.example.com;

    location /ws/ {
        proxy_pass http://backend;

        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

说明:

  • WebSocket需要长连接
  • 同一客户端连接到同一服务器

局限性

负载不均

nginx
upstream backend {
    ip_hash;

    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    server 192.168.1.12:8080;
}

问题:

  • 某些IP访问频繁
  • 导致某些服务器负载过高
  • 负载分配不均匀

服务器故障

nginx
upstream backend {
    ip_hash;

    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    server 192.168.1.12:8080;
}

问题:

  • 服务器故障后,客户端会话丢失
  • 需要重新建立会话
  • 影响用户体验

替代方案

一致性哈希

nginx
upstream backend {
    hash $request_uri consistent;

    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    server 192.168.1.12:8080;
}

说明:

  • 更灵活的哈希key
  • 支持一致性哈希
  • 适合缓存场景

共享会话存储

nginx
upstream backend {
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    server 192.168.1.12:8080;
}

说明:

  • 使用Redis等存储会话
  • 不依赖IP Hash
  • 更好的负载均衡

常见问题

会话丢失

原因: 服务器故障或重启

解决: 使用共享会话存储

nginx
upstream backend {
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
}

负载不均

原因: 某些IP访问频繁

解决: 使用其他算法或共享会话存储

nginx
upstream backend {
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
}

代理IP问题

原因: 客户端通过代理访问

解决: 使用X-Forwarded-For

nginx
map $http_x_forwarded_for $client_ip {
    default $remote_addr;
    ~^([0-9.]+) $1;
}

upstream backend {
    ip_hash;

    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
}

总结

IP Hash配置的关键点:

  • ip_hash:启用IP Hash算法
  • 会话保持:同一IP分配到同一服务器
  • 适用场景:有状态应用、WebSocket
  • 局限性:负载不均、服务器故障影响
  • 替代方案:一致性哈希、共享会话存储

IP Hash适合需要会话保持的场景,但需要注意其局限性。