Nginx解决前后端分离架构下的Session共享的几种方法

 更新时间:2026年04月20日 10:33:37   作者:舞夢輝影  
本文主要介绍了Nginx解决前后端分离架构下的Session共享的几种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

前后端分离的 Session 困境

传统单体架构:
用户 → Nginx → Tomcat/PHP
              ↓
           Session 存储在内存(单机无问题)

前后端分离架构:
用户 → Nginx → 前端服务器 (Vue/React 静态资源)
              ↓
            API 网关 → 后端服务集群 (Tomcat-A, Tomcat-B, Tomcat-C)
                          ↓
                    Session 存储在各自内存(用户请求被负载到不同节点,Session 丢失!)

核心问题:负载均衡后,同一用户的请求可能落到不同后端节点,导致 Session 不一致。

方案一:Nginx 粘性会话(Sticky Session)

让同一用户的请求始终落到同一后端节点。

1. 基于 IP Hash(简单但粗糙)

upstream backend {
    # 根据客户端 IP 的 hash 值分配后端
    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 api.example.com;
    location /api/ {
        proxy_pass http://backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

缺点

  • 用户 IP 变化(移动网络、代理)会切换节点
  • 某节点故障时,该节点用户 Session 丢失
  • 无法动态扩容(增减节点导致 hash 重新计算)

2. 基于 Cookie 的粘性会话(推荐)

使用 sticky 模块或第三方模块:

# 需要编译安装 nginx-sticky-module
upstream backend {
    sticky cookie srv_id expires=1h domain=.example.com path=/;
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    server 192.168.1.12:8080;
}
server {
    location /api/ {
        proxy_pass http://backend;
    }
}

原理:Nginx 设置 Cookie srv_id=后端标识,后续请求根据 Cookie 值路由。

方案二:Session 集中存储(推荐)

将 Session 从应用内存剥离,存储到共享中间件。

架构图

用户请求 → Nginx → 后端服务A
              ↓       ↓
              ↓    读写 Session
              ↓       ↓
            Redis/MySQL(Session 存储中心)
              ↑       ↑
              ↑    读写 Session
              ↑       ↓
            后端服务B(获取同一 Session)

1. Spring Boot + Redis 配置示例

// application.yml
spring:
  session:
    store-type: redis
    redis:
      namespace: myapp:session
      flush-mode: on_save
      cleanup-cron: 0 */30 * * * *
  redis:
    host: 192.168.1.50
    port: 6379
    password: secret
    timeout: 2000ms
    lettuce:
      pool:
        max-active: 8
        max-idle: 8
        min-idle: 0
server:
  servlet:
    session:
      timeout: 30m  # Session 过期时间

2. Nginx 负载均衡配置(无状态)

upstream backend {
    # 无需 ip_hash,纯轮询即可
    least_conn;  # 最少连接数优先,更智能
    server 192.168.1.10:8080 weight=5;
    server 192.168.1.11:8080 weight=5;
    server 192.168.1.12:8080 backup;  # 备用节点
}
server {
    listen 80;
    server_name api.example.com;
    # 跨域配置(前后端分离必需)
    location /api/ {
        # 处理预检请求
        if ($request_method = 'OPTIONS') {
            add_header 'Access-Control-Allow-Origin' 'https://frontend.example.com';
            add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';
            add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization';
            add_header 'Access-Control-Allow-Credentials' 'true';
            add_header 'Access-Control-Max-Age' 1728000;
            add_header 'Content-Type' 'text/plain; charset=utf-8';
            add_header 'Content-Length' 0;
            return 204;
        }
        proxy_pass http://backend;
        proxy_http_version 1.1;
        # 关键:传递 Cookie 和 Session ID
        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;
        # 确保 Cookie 透传
        proxy_pass_header Set-Cookie;
        proxy_cookie_path / /;
        proxy_cookie_domain backend.example.com .example.com;
    }
}

3. 其他 Session 存储方案对比

方案优点缺点适用场景
Redis速度快,支持过期,分布式友好需额外维护 Redis高并发,大规模集群
MySQL/PostgreSQL持久化好,已有数据库复用性能较低,频繁读写压力大小规模,已有数据库
Memcached纯内存,极快无持久化,数据易失纯缓存场景,可容忍丢失
JWT(无 Session)服务端无状态,天然分布式Token 无法主动失效,体积大微服务,API 网关

方案三:JWT Token 替代 Session(无状态架构)

彻底抛弃服务端 Session,改用 Token 认证。

认证流程

1. 用户登录 → 后端验证 → 生成 JWT(含用户ID、权限、过期时间)
                    ↓
2. 返回 Token 给前端 → 前端存储(localStorage 或 Cookie)
                    ↓
3. 后续请求 → 前端在 Header 携带 Authorization: Bearer <token>
                    ↓
4. Nginx 透传 → 后端验签 → 无需查 Session,直接获取用户信息

Nginx 配置(JWT 透传)

server {
    listen 80;
    server_name api.example.com;
    location /api/ {
        proxy_pass http://backend;
        # 关键:透传 Authorization Header
        proxy_set_header Authorization $http_authorization;
        proxy_pass_header Authorization;
        # 其他标准配置
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        # 可选:Nginx 层 JWT 验签(减轻后端压力,需 ngx_http_auth_jwt_module)
        # auth_jwt "API";
        # auth_jwt_key_file /etc/nginx/jwt_key.pub;
    }
}

JWT vs Session 对比

特性Session + RedisJWT
服务端状态有状态(存 Redis)无状态
横向扩展需 Redis 集群天然支持
登出/踢人立即删除 Session需黑名单机制(Redis)
性能每次查 Redis本地验签,更快
安全性可控制,服务端掌握Token 泄露后无法撤销(除非短过期+刷新)
适用传统 Web,需强控制微服务,移动端,API

方案四:Nginx + Lua 实现共享 Session(OpenResty)

在 Nginx 层统一处理 Session,后端完全无感知。

# 使用 OpenResty + lua-resty-session
server {
    listen 80;
    server_name app.example.com;
    location / {
        access_by_lua_block {
            local session = require "resty.session".start()
            -- 检查登录状态
            if not session.data.user_id then
                -- 未登录,重定向到登录页
                return ngx.redirect("/login")
            end
            -- 已登录,将用户信息注入 Header 传给后端
            ngx.req.set_header("X-User-ID", session.data.user_id)
            ngx.req.set_header("X-User-Role", session.data.role)
        }
        proxy_pass http://backend;
    }
    location /login {
        content_by_lua_block {
            -- 处理登录逻辑,写 Session 到 Redis
            local session = require "resty.session".start()
            session.data.user_id = ngx.var.arg_username
            session.data.role = "admin"
            session:save()
            ngx.say("Login success")
        }
    }
}

优势:后端完全无 Session 逻辑,专注业务;Nginx 层统一认证入口。

生产环境推荐配置

完整 Nginx 配置(Redis Session + 负载均衡)

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
    worker_connections 1024;
}
http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    # 日志格式(记录 Session ID)
    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for" '
                    'session=$cookie_SESSION';  # 记录 Session Cookie
    access_log /var/log/nginx/access.log main;
    # 上游后端(无状态,纯轮询)
    upstream api_backend {
        zone backend 64k;
        least_conn;
        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;
        keepalive 32;  # 长连接,提升性能
    }
    # 前端静态资源(CDN 或本地)
    server {
        listen 80;
        server_name www.example.com;
        root /var/www/frontend;
        location / {
            try_files $uri $uri/ /index.html;
            expires 1h;
        }
        # 静态资源缓存
        location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
            expires 30d;
            add_header Cache-Control "public, immutable";
        }
    }
    # API 网关
    server {
        listen 80;
        server_name api.example.com;
        # 安全头
        add_header X-Frame-Options "SAMEORIGIN" always;
        add_header X-Content-Type-Options "nosniff" always;
        add_header X-XSS-Protection "1; mode=block" always;
        # 跨域(生产环境限制具体域名)
        map $http_origin $cors_origin {
            default "";
            "~^https?://(.*\.)?example\.com$" $http_origin;
            "~^https?://localhost:\d+$" $http_origin;
        }
        location /api/ {
            # CORS 处理
            if ($request_method = 'OPTIONS') {
                add_header 'Access-Control-Allow-Origin' $cors_origin;
                add_header 'Access-Control-Allow-Credentials' 'true';
                add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';
                add_header 'Access-Control-Allow-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With';
                add_header 'Access-Control-Max-Age' 1728000;
                add_header 'Content-Type' 'text/plain; charset=utf-8';
                add_header 'Content-Length' 0;
                return 204;
            }
            add_header 'Access-Control-Allow-Origin' $cors_origin always;
            add_header 'Access-Control-Allow-Credentials' 'true' always;
            proxy_pass http://api_backend;
            proxy_http_version 1.1;
            # 连接优化
            proxy_connect_timeout 5s;
            proxy_send_timeout 60s;
            proxy_read_timeout 60s;
            # 缓冲区
            proxy_buffering on;
            proxy_buffer_size 4k;
            proxy_buffers 8 4k;
            # 关键:Session/Cookie 透传
            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_set_header X-Forwarded-Host $host;
            proxy_set_header X-Forwarded-Port $server_port;
            # Cookie 处理
            proxy_pass_header Set-Cookie;
            proxy_cookie_path / /;
            # 长连接
            proxy_set_header Connection "";
        }
        # 健康检查(需 nginx_upstream_check_module)
        location /health {
            access_log off;
            return 200 "healthy\n";
            add_header Content-Type text/plain;
        }
    }
}

方案选择建议

场景推荐方案理由
中小型项目,快速上线Nginx ip_hash零代码改动,快速解决
中大型项目,长期维护Redis Session标准方案,生态成熟
微服务/云原生架构JWT + API 网关无状态,天然适合容器化
极高性能要求OpenResty Lua Session减少后端交互,Nginx 层处理

核心原则:Session 共享的本质是让状态外置,Nginx 作为入口只需做好透明透传和负载均衡。

到此这篇关于Nginx解决前后端分离架构下的Session共享的几种方法的文章就介绍到这了,更多相关Nginx Session共享内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Nginx日志配置及状态监控方式解读

    Nginx日志配置及状态监控方式解读

    文章详细介绍了Nginx的配置技巧,包括日志配置(如access_log、log_format等模块)、状态监控(如stub_status_model编译选项)以及高级配置(如log_not_found、log_subrequest等),帮助用户全面掌握Nginx的日志管理和状态监控方法
    2025-09-09
  • nginx lua集成kafka的实现方法

    nginx lua集成kafka的实现方法

    这篇文章主要介绍了nginx lua集成kafka的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-08-08
  • 前端开发用得着的nginx配置(场景)

    前端开发用得着的nginx配置(场景)

    这篇文章主要介绍了前端开发用得着的nginx配置,前端的工作过程里,本地开发、提供测试环境,总得有个用着顺手的服务器软件,这个场景里nginx很流行,特分享下需要的朋友可以参考下
    2014-09-09
  • Nginx设置HttpOnly Secure SameSite参数解决Cookie信息丢失

    Nginx设置HttpOnly Secure SameSite参数解决Cookie信息丢失

    本文主要介绍了Nginx中Cookie缺少SameSite属性的问题,并详细解释了HttpOnly、Secure和SameSite属性的作用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-11-11
  • Nginx进行域名重写和泛域名解析配置的方法

    Nginx进行域名重写和泛域名解析配置的方法

    这篇文章主要介绍了Nginx进行域名重写和泛域名解析配置的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-08-08
  • Nginx虚拟主机的搭建的实现步骤

    Nginx虚拟主机的搭建的实现步骤

    本文主要介绍了Nginx虚拟主机的搭建的实现步骤,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • nginx搭建文件服务器的详细过程

    nginx搭建文件服务器的详细过程

    这篇文章主要介绍了nginx搭建文件服务器,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-06-06
  • nginx的80端口无法被远程服务器访问的问题解决

    nginx的80端口无法被远程服务器访问的问题解决

    这篇文章主要介绍了nginx的80端口无法被远程服务器访问的问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-07-07
  • Nginx上传文件出现“ 413 (499 502 404) Request Entity Too Large错误解决

    Nginx上传文件出现“ 413 (499 502 404) Requ

    HTTP 413 Request Entity Too Large错误常常出现在客户端发送的请求体超过服务器允许的大小限制时,本文主要介绍了Nginx上传文件出现“ 413 (499 502 404) Request Entity Too Large错误解决,感兴趣的可以了解一下
    2024-07-07
  • 三步配置轻量级服务器nginx小结

    三步配置轻量级服务器nginx小结

    Nginx是一个安装非常的简单 , 配置文件非常简洁,本文就来介绍一下三步配置轻量级服务器nginx,具有一定的参考价值,感兴趣的可以了解一下
    2023-08-08

最新评论