nginx 会话保持

对于经过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-module
    sticky;
    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;
}

注意事项

  1. NAT用户特征:同一NAT下的用户共享公网IP,不能依赖源IP进行会话保持

  2. 会话超时:设置合理的会话超时时间,避免长时间占用服务器资源

  3. 服务器下线:当后端服务器下线时,相关会话需要重新分配

  4. 负载均衡:确保会话保持不会导致负载不均衡

  5. 加密传输:对于敏感信息,建议使用HTTPS加密传输

选择哪种方式取决于你的具体应用场景和技术栈。对于大多数Web应用,基于Cookie的会话保持是最常用且有效的方法。

 
 
 
posted @ 2025-11-20 10:30  滴滴滴  阅读(19)  评论(0)    收藏  举报