RedisCluser(v-3.2.0)与Tomcat7的Session整合

来源:互联网 发布:安阳战狼网络会所电话 编辑:程序博客网 时间:2024/06/06 00:26
一般情况下,一个web系统的架构是类似这样的:
一个或多个nginx做负载均衡,后面连多个tomcat(或别的类型的web服务器)。
nginx做负载的时候,关于request的分流,至少就有两种策略,第一种就是根据请求的ip做hash,这样能保证同一个ip的请求都映射到同一个tomcat上。第二种,就是直接按照时间或者后端服务器的性能,负载等条件进行分流,那么这样,比如就会产生session问题。
所以一般的web系统,会把用户的session单独放到一个服务器上,业内大多使用Redis来存储用户session。
这种架构,后端可以使用一个redis实例,也可以使用多个redis实例。
如果是单redis的话,与tomcat整合比较简单
见下文
http://blog.csdn.net/qq584852076/article/details/46502185


但是,如果只有一个redis,总感觉有点不安全,我们可以使用多个redis。
一般的架构如图:


OK,在这篇博客里
我用了一个nginx,版本号1.10.2
2个tomcat,版本号都是7.0.68
6个Redis实例构成的RedisCluster,版本号是3.2.0。集群的模式,就是官方推出的Cluster,key在服务器端分流。关于redis集群的构建,大家可以参考http://blog.csdn.net/xu470438000/article/details/42971091
我当时在搭建redis集群的时候,碰到的最大的问题就是关于ruby组件的使用。
太tm丢人了。
当时总是出现./redis-trib.rb:24:in `require': no such file to load -- rubygems (LoadError)
后来误打误撞解决了问题。
似乎当时使用了rvm选择了默认的ruby版本才OK的
参见:https://my.oschina.net/junfrost/blog/143487


OK,行文到此,我默认大家目前都已经把nginx和redis集群都搭建好了(其实这篇文章里面的技术和nginx没关系)
那么单redis和rediscluster的使用有什么区别么?
单redis的java客户端使用的是jedis,例子如下:
 Jedis jedis=new Jedis("192.168.0.100", 6379); jedis.set("name","xinxin");
 如果是使用JedisPool那后面就要close一下,差别不大
RedisCluster的java客户端使用的不是jedis而是JedisCluster,例子如下:
String key = "2";        // 这东西 可以直接看到key 的分片数,就能知道放哪个 节点        System.out.println(JedisClusterCRC16.getSlot(key));        Set<HostAndPort> jedisClusterNodes = new HashSet<HostAndPort>();        jedisClusterNodes.add(new HostAndPort("127.0.0.1", 7000));        jedisClusterNodes.add(new HostAndPort("127.0.0.1", 7001));        jedisClusterNodes.add(new HostAndPort("127.0.0.1", 7002));        // 3个master 节点        JedisCluster jc = new JedisCluster(jedisClusterNodes);        System.out.println(jc.get(key));        jc.setnx(key, "bar");        String value = jc.get(key);        System.out.println(value);
那JedisCluster的连接池呢?有没有JedisClusterPool?答案是没有。
为啥没有?
因为JedisCluster内部就有池的实现。同时JedisCluser的get/set/exist都是使用的模板模式,connection是共用的。如果还不清楚,那就去看源码
参见 http://brandnewuser.iteye.com/blog/2312071


大家明白了么?
我们按照http://blog.csdn.net/qq584852076/article/details/46502185 这篇博客里说的
tomcat-redis-session-manager
里面使用的Jedis!
那么如果我使用的RedisCluster的集群模式
改动tomcat的context.xml,如下:(同时那几个jar包也得放进去,参见之前的 单redis与tomcat整合)
<?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="localhost"            port="6379"            database="0"            maxInactiveInterval="60" />  <!----------------------------- -->  </Context>  
会如何呢?
会报这个错误:



这个错误是什么意思?
你用jedis去连接RedisCluster还问我为什么!!!???
那咋办?改呗。改什么?改tomcat-redis-session-manager的源码呗。
我们根据上面那个错误,可以看到问题发生在RedisSessionManager的loadSessionDataFromRedis方法。

源码如下:

 //RedisSessionManager.java  public byte[] loadSessionDataFromRedis(String id) throws IOException {    Jedis jedis = null;    Boolean error = true;    try {      log.trace("Attempting to load session " + id + " from Redis");      jedis = acquireConnection();      byte[] data = jedis.get(id.getBytes());      error = false;      if (data == null) {        log.trace("Session " + id + " not found in Redis");      }      return data;    } finally {      if (jedis != null) {        returnConnection(jedis, error);      }    }  }

看到了吧,使用的是jedis。
那既然知道问题了,那就好改了
大体的说:把Jedis改成JedisCluster即可
但是具体要改的的地方还不少,代码我就不贴上来了,具体见:
https://github.com/cxyxd/tomcat-redis-session-manager/blob/master/src/main/java/com/orangefunction/tomcat/redissessions/RedisSessionManager.java


这个项目用的别的组件如下:
  compile group: 'org.apache.tomcat', name: 'tomcat-catalina', version: '7.0.68'  compile group: 'redis.clients', name: 'jedis', version: '2.8.2'  compile group: 'org.apache.commons', name: 'commons-pool2', version: '2.4.2'

我靠你说了半天,整合rediscluster(v-3.2.0)与tomcat7的最主要的jar包在哪么?

http://pan.baidu.com/s/1dEZZFmp
本来想直接上传到csdn的资源栏目的,不过传了几次都是错误。


好的我们看看效果

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"    pageEncoding="ISO-8859-1"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>Insert title here</title></head><body>/usr/local/tomcat7_forZW/webapps/PathTest--8080<br>SessionID:<%=session.getId()%></body></html>
我们在两个tomcat下都放一个sessiontest.jsp,内容如上

/usr/local/tomcat7_forZW/webapps/PathTest--8080这是tomcat的地址与端口号,两个jsp的这部分内容不一样(一个端口是,8080一个是1314)

我们访问一下:

换个地址,结果如下:

我们再去看看redis里面





参考资料
jredis cluster客户端使用
JedisCluster中应用的Apache Commons Pool对象池技术
tomcat7 redis session 共享
0 0