对于经过NAT网关的用户,nginx可以通过以下几种方式实现会话保持:
1. 基于Cookie的会话保持
1.1 sticky-cookie模块
nginx
upstream backend {server 192.168.1.10:8080;server 192.168.1.11:8080;# 使用sticky cookie实现会话保持sticky cookie srv_id expires=1h domain=.example.com path=/;
}
1.2 第三方sticky模块
nginx
upstream backend {server 192.168.1.10:8080;server 192.168.1.11:8080;# 使用nginx-sticky-modulesticky;sticky_hide_cookie upstream=;
}
2. 基于URI的会话保持
nginx
upstream backend {hash $request_uri consistent;server 192.168.1.10:8080;server 192.168.1.11:8080;
}
3. 基于自定义Header的会话保持
nginx
# 提取用户标识Header
map $http_x_user_id $backend_pool {default "";"~*" $http_x_user_id;
}upstream backend {hash $backend_pool consistent;server 192.168.1.10:8080;server 192.168.1.11:8080;
}
4. 应用层会话标识
4.1 基于Session ID
nginx
# 从Cookie中提取session id
map $cookie_jsessionid $session_backend {default "";"~*(.+)" $1;
}upstream backend {hash $session_backend consistent;server 192.168.1.10:8080;server 192.168.1.11:8080;
}
4.2 基于Token
nginx
# 从Authorization头提取token
map $http_authorization $token_backend {default "";"~*Bearer\s+(.+)" $1;
}upstream backend {hash $token_backend consistent;server 192.168.1.10:8080;server 192.168.1.11:8080;
}
5. 完整的NAT用户会话保持配置示例
nginx
http {# 定义后端服务器组upstream backend_servers {# 使用consistent hash算法hash $consistent_key consistent;server 192.168.1.10:8080 weight=3;server 192.168.1.11:8080 weight=2;server 192.168.1.12:8080 weight=1;}# 定义一致性hash的key# 优先级:session id > user token > 其他标识map $cookie_sessionid $consistent_key {default $cookie_sessionid;"" $http_x_user_token;}map $consistent_key $consistent_key_final {default $consistent_key;"" $remote_addr$http_user_agent; # 最后回退到IP+UA组合}server {listen 80;server_name example.com;location / {# 设置会话保持cookie(如果应用没有提供)add_header Set-Cookie "sessionid=$upstream_http_x_session_id; Path=/; HttpOnly" always;proxy_pass http://backend_servers;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_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;proxy_connect_timeout 30s;proxy_read_timeout 30s;}# 健康检查端点location /health {access_log off;proxy_pass http://backend_servers;}}
}
6. 使用Nginx Plus的会话保持功能
如果使用Nginx Plus,可以使用更强大的会话保持功能:
nginx
upstream backend {zone backend 64k;server 192.168.1.10:8080;server 192.168.1.11:8080;# Nginx Plus的sticky route功能sticky route $route_cookie $route_uri;
}
7. 针对不同场景的建议
7.1 Web应用场景
nginx
# 优先使用session cookie
map $cookie_jsessionid $backend_key {default $cookie_jsessionid;"" $cookie_phpsessid;
}upstream web_backend {hash $backend_key consistent;server 192.168.1.10:8080;server 192.168.1.11:8080;
}
7.2 API服务场景
nginx
# 使用API token或自定义header
map $http_authorization $api_key {default $http_authorization;"" $http_x_api_key;
}upstream api_backend {hash $api_key consistent;server 192.168.1.20:8080;server 192.168.1.21:8080;
}
注意事项
-
NAT用户特征:同一NAT下的用户共享公网IP,不能依赖源IP进行会话保持
-
会话超时:设置合理的会话超时时间,避免长时间占用服务器资源
-
服务器下线:当后端服务器下线时,相关会话需要重新分配
-
负载均衡:确保会话保持不会导致负载不均衡
-
加密传输:对于敏感信息,建议使用HTTPS加密传输
选择哪种方式取决于你的具体应用场景和技术栈。对于大多数Web应用,基于Cookie的会话保持是最常用且有效的方法。