使用Redis存储Nginx+Tomcat负载均衡集群的Session

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
应用型负载均衡 ALB,每月750个小时 15LCU
简介: 环境:Cent OS 7.0(虚拟机环境)、Nginx 1.9.8、Redis 3.2.1一、背景在使用Nginx+Tomcat实现负载均衡的时候,由于Nginx对不同的请求分发到某一个Tomcat,Tomcat在运行的时候分别是不同的容器里,因为会出现session不同步或者丢失的问题。二、Nginx安装与配置1、Nginx安装网上的资源对于安装Nginx的介绍比较多,例如最

环境:Cent OS 7.0(虚拟机环境)、Nginx 1.9.8、Redis 3.2.1

一、背景

在使用Nginx+Tomcat实现负载均衡的时候,由于Nginx对不同的请求分发到某一个Tomcat,Tomcat在运行的时候分别是不同的容器里,因为会出现session不同步或者丢失的问题。

二、Nginx安装与配置

1、Nginx安装

网上的资源对于安装Nginx的介绍比较多,例如最简单的为:

1) 获取nginx,在http://nginx.org/download/上可以获取当前最新的版本下载,例如:

wget http://nginx.org/download/nginx-1.9.8.tar.gz2)解压缩tar -xvf nginx-1.9.8.tar.gz包。

(3)进入解压缩目录,执行./configure --prefix=/usr/local/nginx-1.9.8 将Nginx安装到/usr/local/nginx-1.9.8目录下

(4)make & make install
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

安装的过程会将Nginx安装到/usr/local/nginx-1.9.8目录下,启动Nginx测试是否可以正常启动。

2、修改Nginx配置多Tomcat服务器

2.1、修改conf/nginx.conf文件,在server标签上边添加upstream如下:

 upstream mynginxserver {
    #weigth参数表示权值,权值越高被分配到的几率越大
    #本机上的Squid开启3128端口
        server 127.0.0.1:8080 weight=1;
        server 127.0.0.1:8060 weight=1;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

这里指定了本机下的两个Tomcat实例,端口分别为8080,8060,权重都为1,后边配置Tomcat实例,mynginxserver这个是自己随意命名的,下边要用到

2.2、配置server标签;

 server {
        listen       80;
        server_name  192.168.1.149;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
           # root   html;
           # index  index.html index.htm;
           proxy_pass http://mynginxserver;
        }


        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

2.3、配置之后的完整内容如下(1.9.8版本删去了注释后的配置内容):

worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;

    keepalive_timeout  65;

    upstream mynginxserver {
        server 127.0.0.1:8080 weight=1;
        server 127.0.0.1:8060 weight=1;
    }

    server {
        listen       80;
        server_name  192.168.1.149;

        location / {
           proxy_pass http://mynginxserver; 
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}
  • 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
  • 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

2.4、具体的配置项和配置项的具体意义请参考 
https://www.nginx.com/resources/wiki/start/topics/examples/full/

三、Tomcat多实例的配置

1、解压apache-tomcat-7.0.67.zip 得到apache-tomcat-7.0.67

[root@localhost www]# unzip apache-tomcat-7.0.67.zip
  • 1
  • 2
  • 1
  • 2

2、将apache-tomcat-7.0.67重命名为tomcat1

[root@localhost www]# mv apache-tomcat-7.0.67 tomcat1
  • 1
  • 2
  • 1
  • 2

重复1、2过程得到tomcat1和tomcat2如下所示:

这里写图片描述

3、修改Tomcat1的端口为8080和部署项目文件

编辑tomcat下的conf/server.xml,修改端口号为8080,

自己写的用于测试Nginx反向代理的web项目war包下载地址:http://download.csdn.net/detail/u010870518/9585683

下载好之后将解压之后的编译好的项目文件放到tomcat1/webapps/ROOT/目录下:

这里写图片描述

修改index.jsp和login.jsp文件分别标识为具体的Tomcat容器

这里写图片描述

4、修改Tomcat2的端口为8060和部署项目文件

编辑tomcat下的conf/server.xml,修改端口号为8060,然后和上述3中的一样,下载war内容,放在tomcat2/webapps/ROOT/下,修改index.jsp和login.jsp用于标识具体的Tomcat容器

5、分别启动tomcat1和tomcat2

6、重启Nginx服务,访问IP地址:192.168.1.149:80(这个是访问的虚拟机IP地址)

7、观看效果

这里写图片描述

这里写图片描述

可以看出,Nginx已经进行了请求分发,转发到具体的某一个Tomcat

四、Redis的安装与配置

由于篇幅过长,请参考本人写的:http://blog.csdn.net/xlgen157387/article/details/52022793

五、tomcat-redis-session-manager开源项目的使用

1、开源项目地址:https://github.com/jcoleman/tomcat-redis-session-manager

2、下载代码之后需要进行重新编译,生成所需要的jar,任意创建maven项目,将src下的代码拷贝到具体位置,如下:

这里写图片描述

maven的pom.xml文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.ufind.session</groupId>
    <artifactId>tomcat-redis-session</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-catalina</artifactId>
            <version>7.0.27</version>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.7.2</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.0</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>
  • 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
  • 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

3、然后打开terminal,执行mvn clean 和mvn install 将编译好的代码打包为:tomcat-redis-session-1.0-SNAPSHOT.jar

4、将tomcat-redis-session-1.0-SNAPSHOT.jar、jedis-2.7.2.jar、commons-pool2-2.0.jar 三个jar包分别放在tomcat1和tomcat2实例下的lib目录下。

免费下载这三个jar:http://download.csdn.net/detail/u010870518/9585716

5、修改tomcat实例下conf/contex.xml文件

<?xml version='1.0' encoding='utf-8'?>  
<Context>  
    <WatchedResource>WEB-INF/web.xml</WatchedResource>  

    <!-- tomcat-redis-session共享配置 -->  
    <Valve className="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve" />  
        <Manager className="com.orangefunction.tomcat.redissessions.RedisSessionManager"  
         host="192.168.1.149"   
         port="6379"   
         database="0"   
         maxInactiveInterval="60" />  

</Context>  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

如果Redis配置了访问权限,请添加密码为:

<?xml version='1.0' encoding='utf-8'?>  
<Context>  
    <WatchedResource>WEB-INF/web.xml</WatchedResource>  

    <!-- tomcat-redis-session共享配置 -->  
    <Valve className="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve" />  
        <Manager className="com.orangefunction.tomcat.redissessions.RedisSessionManager"  
         host="192.168.1.149"   
         port="6379"   
         database="0"  
         password="redispassword" 
         maxInactiveInterval="60" />  

</Context>  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

如果不设置密码会报错,如下:

这里写图片描述

六、效果演示

案例演示的一个登陆请求,登陆成功之后将用户信息放在session中,在界面中显示出来(tomcat1实例,tomcat2的实例中只是在 h2 标签中做了一下标识)

1、login.jsp文件:

<body>
<h2>Session Demo in Tomcat1</h2>
<form action="/user?type=login" method="post">
    用户名:<input type="text" name="userName"/><br/>
    密码:<input type="password" name="userPassword"/><br/>
    <input type="submit" value="login">
</form>
</body>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

2、index.jsp 将登录之后的信息显示在界面上

<body>

<h2>Session Demo in Tomcat1</h2>

<%
    User user = (User) request.getSession().getAttribute("USER");
    if (user == null) {
%>
用户为空,没有登录!!!
<%
} else {
%>
欢迎: <%=user.getUserName()%>
<%
    }
%>

</body>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

3、servlet处理请求代码

public class UserServlet extends BaseServlet {

    public String login(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        User user = new User();
        user.setUserName(request.getParameter("userName"));
        user.setUserPassword(request.getParameter("userPassword"));
        request.getSession().setAttribute("USER", user);

        return "index.jsp";
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

4、效果如下:

这里写图片描述

可以看出在登录界面的时候刷新请求的tomcat已经由Nginx进行分发请求,登录之后再两个tomcta中已经共享了session

5、查看Redis对session的存储

在对contex.xml文件进行配置的时候默认使用的database为0,通过redis-cli工具可看到

这里写图片描述

这里写图片描述

七、总结

tomcat-redis-session-manager是一个对用户完全透明的分布式session存储框架,用户只需要在tomcat中进行简单的配置,就可以使用,我们的业务代码是完全和单实例的时候的代码是一样的的,也就是写代码的时候完全不用担心你写的是一个多tomcat实例的代码,完全透明。

如何对框架的原理进行简单的理解,我们首先要知道,在请求过程中的session操作,首先要解析请求中的sessionId信息,然后将sessionId存储到request的参数列表中。然后再从 request获取session的时候,如果存在sessionId那么就根据Id从session池中获取session,如果sessionId不存在或者session失效,那么则新建session并且将session信息放入session池,供下次使用。

如果我们想自己写一个类似于tomcat-redis-session-manager的项目,我们应该知道Tomcat的Session管理机制,在默认的情况下Tomcat的Session管理,如果不进行设置的话是由Tomcat自带的StandardManager类进行控制的,我们可以根据这个类自定义一个Manager,主要重写的就是org.apache.catalina.session.ManagerBase里边的具体写的操作, 
这也是tomcat-redis-session-manager的基本原理,将tomcat的session存储位置指向了Redis

这里写图片描述

RedisSessionManager继承了org.apache.catalina.session.ManagerBase并重写了add、findSession、createEmptySession、remove等方法,并将对session的增删改查操作指向了对Redis数据存储的操作

有兴趣可参考一篇Tomcat中session的管理机制:http://www.cnblogs.com/interdrp/p/4935614.html

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
2月前
|
存储 缓存 NoSQL
数据的存储--Redis缓存存储(一)
数据的存储--Redis缓存存储(一)
|
2月前
|
存储 缓存 NoSQL
数据的存储--Redis缓存存储(二)
数据的存储--Redis缓存存储(二)
数据的存储--Redis缓存存储(二)
|
2月前
|
消息中间件 缓存 NoSQL
Redis 是一个高性能的键值对存储系统,常用于缓存、消息队列和会话管理等场景。
【10月更文挑战第4天】Redis 是一个高性能的键值对存储系统,常用于缓存、消息队列和会话管理等场景。随着数据增长,有时需要将 Redis 数据导出以进行分析、备份或迁移。本文详细介绍几种导出方法:1)使用 Redis 命令与重定向;2)利用 Redis 的 RDB 和 AOF 持久化功能;3)借助第三方工具如 `redis-dump`。每种方法均附有示例代码,帮助你轻松完成数据导出任务。无论数据量大小,总有一款适合你。
78 6
|
4月前
|
存储 缓存 NoSQL
【Azure Redis 缓存】关于Azure Cache for Redis 服务在传输和存储键值对(Key/Value)的加密问题
【Azure Redis 缓存】关于Azure Cache for Redis 服务在传输和存储键值对(Key/Value)的加密问题
|
4月前
|
监控 NoSQL Redis
看完这篇就能弄懂Redis的集群的原理了
看完这篇就能弄懂Redis的集群的原理了
140 0
|
17天前
|
存储 NoSQL 算法
Redis分片集群中数据是怎么存储和读取的 ?
Redis集群采用哈希槽分区算法,共有16384个哈希槽,每个槽分配到不同的Redis节点上。数据操作时,通过CRC16算法对key计算并取模,确定其所属的槽和对应的节点,从而实现高效的数据存取。
44 13
|
17天前
|
存储 NoSQL Redis
【赵渝强老师】Redis的存储结构
Redis 默认配置包含 16 个数据库,通过 `databases` 参数设置。每个数据库编号从 0 开始,默认连接 0 号数据库,可通过 `SELECT &lt;dbid&gt;` 切换。Redis 的核心存储结构包括 `dict`、`expires` 等字段,用于处理键值和过期行为。添加键时需指定数据库信息。视频讲解和代码示例详见内容。
|
3月前
|
存储 NoSQL Redis
2)Redis 的键值对长什么样子,又是怎么存储的?
2)Redis 的键值对长什么样子,又是怎么存储的?
46 0
|
4月前
|
负载均衡 算法 应用服务中间件
负载均衡技术在Web服务器集群中的应用
【8月更文第28天】随着互联网的发展和用户对Web服务需求的增长,单台服务器很难满足大规模访问的需求。为了提高系统的稳定性和扩展性,通常会采用Web服务器集群的方式。在这种架构中,负载均衡器扮演着至关重要的角色,它能够合理地分配客户端请求到不同的后端服务器上,从而实现资源的最优利用。
129 2
|
4月前
|
存储 消息中间件 NoSQL
Redis命令详解以及存储原理
Redis命令详解以及存储原理