负载均衡Nginx Session 一致性

HTTPS请求跳转

如下面的配置:

1
2
3
location /test {
proxy_pass http://www.baidu.com/;
}

在访问URI为/test时会跳转到百度,但是此时浏览器的URL也发生了变化,这是因为向http://www.baidu.com/发送请求后,Nginx返回的是一个跳转的响应。

此后,客户端会重新向http://www.baidu.com/发送请求(此过程不再经过nginx),所以浏览器发生了跳转,而非 Nginx的负载均衡。

解决方式: 将配置中的http改成https即可

Session一致性

在使用nginx做反向代理时,如果后端服务器时Tomcat等动态服务器,可能会出现Session一致性的问题。即无法确保同一个Session一定对应同一个Server

  1. 配置IP地址

    Server IP
    Nginx 172.20.1.10
    Server1 172.20.1.101
    Server2 172.20.1.102
    并且在Server1 和 Server2上启动 Tomcat
  2. 配置Server

    在Server段创建jsp页面:

    • Server1

      1
      2
      3
      4
      5
      6
      [root@c5477d71795c ROOT]# pwd
      /var/lib/tomcat/webapps/ROOT
      [root@c5477d71795c ROOT]# cat index.jsp
      from 172.20.1.101
      <br/>
      session=<%=session.getId()%>
    • Server2

      1
      2
      3
      4
      5
      6
      [root@c5477d71795c ROOT]# pwd
      /var/lib/tomcat/webapps/ROOT
      [root@c5477d71795c ROOT]# cat index.jsp
      from 172.20.1.102
      <br/>
      session=<%=session.getId()%>

    然后访问 http://172.20.1.101:8080/http://172.20.1.102:8080/

    可分别显示来自哪个Server和对应的 SessionId,并且刷新页面时 SessionId 不会变化(即使是使用 Ctrl+F5 刷新)

  3. 配置Nginx

    修改Nginx配置文件,加入upstream配置和server配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    upstream tomcat {
    server 172.20.1.101:8080;
    server 172.20.1.102:8080;
    }

    server {
    ......
    location /cat {
    proxy_pass http://tomcat/;
    }
    }

    重启Nginx

    1
    [root@ce12b3b4ce00 sbin]# ./nginx -s reload

    访问 http://172.20.1.10/cat 并刷新,发现 from 172.20.1.10x 一直在变化,并且session=xxx 也变化。

    说明:此时 Nginx 的配置无法保证 Session 一致性!

解决方案

在 Tomcat 后面部署 Redis,MemCached 等内存数据库来保存 Session 相关信息。

本例中在 Nginx 服务器上安装 memcached 来解决 Session 一致性问题。

  1. 启动memcached
    1
    2
    3
    4
    5
    # 1. 安装memcached
    yum install -y memcached

    # 2. 启动memcached
    memcached -d -m 128m -p 11211 -l 172.20.1.10 -u root -P /tmp/
    参数说明
    • -d: 后台启动
    • -m: 缓存大小
    • -p: 端口
    • -l: IP地址
    • -P: 服务启动后系统进程 ID 存储文件的目录
    • -u: 服务器以哪个用户作为管理用户
  2. 修改tomcat配置 在两台Server中修改tomcat配置
    1
    [root@3a53f7504511 ROOT]# vi /etc/tomcat/context.xml 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <!-- context标签中加入下面的内容 --> 
    <Manager
    className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
    memcachedNodes="n1:172.20.1.10:11211"
    sticky="false"
    sessionBackupAsync="false"
    lockingMode="auto"
    requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
    sessionBackupTimeout="1000"
    transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory" />
    导入 jar 包使用 yum 安装的 Tomcat 可将 jar 包放在 /usr/share/java/tomcat/ 目录下。 需要以下jar包:
  1. 添加Maven依赖(Maven项目配置,测试可不加)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    <dependency>
    <groupId>asm</groupId>
    <artifactId>asm</artifactId>
    <version>3.2</version>
    </dependency>

    <dependency>
    <groupId>com.couchbase.client</groupId>
    <artifactId>couchbase-client</artifactId>
    <version>1.4.11</version>
    </dependency>

    <dependency>
    <groupId>com.googlecode</groupId>
    <artifactId>kryo</artifactId>
    <version>1.04</version>
    </dependency>

    <dependency>
    <groupId>de.javakaffee</groupId>
    <artifactId>kryo-serializers</artifactId>
    <version>0.11</version>
    </dependency>

    <dependency>
    <groupId>de.javakaffee.msm</groupId>
    <artifactId>memcached-session-manager</artifactId>
    <version>1.8.2</version>
    </dependency>

    <dependency>
    <groupId>de.javakaffee.msm</groupId>
    <artifactId>memcached-session-manager-tc7</artifactId>
    <version>1.8.2</version>
    </dependency>

    <dependency>
    <groupId>com.googlecode</groupId>
    <artifactId>minlog</artifactId>
    <version>1.2</version>
    </dependency>

    <dependency>
    <groupId>de.javakaffee.msm</groupId>
    <artifactId>msm-kryo-serializer</artifactId>
    <version>1.8.2</version>
    </dependency>

    <dependency>
    <groupId>com.esotericsoftware</groupId>
    <artifactId>reflectasm</artifactId>
    <version>1.01</version>
    </dependency>

    <dependency>
    <groupId>net.spy</groupId>
    <artifactId>spymemcached</artifactId>
    <version>2.11.4</version>
    </dependency>
    注: 如果依赖和 Tomcat 版本不对应可能会什么也不显示,此时响应码为 500。
  1. 验证

    上述步骤都正确配置之后, 再次访问 http://172.20.1.10/cat 并刷新会发现 SessionId 不再变化。