集群session共享方案

1,508 阅读12分钟

在Web项目开发中,会话管理是一个很重要的部分,用于存储与用户相关的数据。通常是由符合session规范的容器来负责存储管理,也就是一旦容器关闭,重启会导致会话失效。因此打造一个高可用性的系统,必须将session管理从容器中独立出来。而这实现方案有很多种,下面简单介绍下(仅限目前自己已知的):

  第一种:使用硬件F5做粘性会话(不会,只是知道可以这么干),成本太高,后期也不好维护。

第二种:使用Nginx的ip_hash特性做粘性会话,可以让用户每次访问都转发到该用户第一次访问的web容器上,但是当该web容器上的应用挂了,nginx不会将该用户的请求转发到别的web容器,体验不好。

第三种:基于cookie实现,将session直接存储到cookie中(安全问题,虽然可以加密存储,但是觉得不能将敏感数据放在客户端)

第四种:使用容器扩展来实现,大家比较容易接受的是通过容器插件来实现,比如基于Tomcat的memcached-session-manager / tomcat-redis-session-manager,基于Jetty的jetty-nosql-memcache / jetty-session-redis等等。好处是对项目来说是透明的,无需改动代码。不过前者目前还不支持Tomcat 8,或者说不太完善。此方法过于依赖容器,一旦容器升级或者更换意味着又得从新来过。并且代码不在项目中,对开发者来说维护也是个问题(如果你使用的是weblogic、jboss、websphere等商业web容器,根本没有这种第三方容器扩展,web容器换了厂商就不行了)。

  第五种:自己实现一套会话管理,将session读取/存储到Redis或其他nosql或数据库(网站用户量大的情况下,频繁dml数据,对db压力大)中。很显然这个方案灵活性最大,但开发需要一些额外的时间。弄懂了会挺不错的。

  第六种:使用框架的会话管理工具spring-session,可以理解是替换了Servlet那一套会话管理,既不依赖容器,又不需要改动代码,并且是用了spring-data-redis那一套连接池,可以说是最完美的解决方案。当然,前提是项目要使用Spring Framework才行。

  第七种:如果项目中使用shiro这种自带session(非httpsession)的权限框架,需要重写shiro的SessionDao将session存入redis(或其他)来实现session共享,可以自己重写(也不是很麻烦)或者找现成的(shiro-redis微笑脸,省的自己造轮子了,知道原理就行)。

前三种方案:出于安全、成本(自己搞着玩不好弄)、无法完全做到724365不宕机,个人不推荐。有兴趣的自己研究吧。

剩下的四种方案大体思路其实都一样,存到nosql中(内存读写快啊)。

各方案具体实现思路:

第四种:

直接去这几个插件github地址,人家写的使用方法更全,不在赘述。(看了点redis-session-manager的源码,他是将自定义了一个RedisSession类继承StandardSession类,这个类是tomcat中lib下的类,太依赖容器了,获取session信息从redis中序列化/反序列化出来)

第五种:(参考别人博客,内容直接粘贴过来了,地址在最上面)

要实现将session信息存入redis,总结了下大概是三点: 1.实现httpsession接口,重写我们需要用到的方法,比如set get这些。。balabala一堆...... 2.继承HttpServletRequestWrapper,这个类里面有getSession()方法,我们需要重写,来取自定义session 3.实现filter,用来拦截客户端请求,获取我们自定义的request,从而获得session

具体实现(这个人并没有实现从redis中读取session的操作,需要将request中获取session和产生session都加入redis操作,但是这里的思路需要掌握,很受教,自己想要实现完美挺难的): 1.实现httpsession接口

 
  1. public class HttpSessionWrapper implements HttpSession {
  2. protected final Logger logger = LoggerFactory.getLogger(getClass());
  3. private String sid = "";
  4. private HttpServletRequest request;
  5. private HttpServletResponse response;
  6. private final long creationTime = System.currentTimeMillis();
  7. private final long lastAccessedTime = System.currentTimeMillis();
  8. private SessionMeta meta;
  9. public HttpSessionWrapper() {
  10. }
  11. public HttpSessionWrapper(String sid,SessionMeta meta, HttpServletRequest request,
  12. HttpServletResponse response) {
  13. this.sid=sid;
  14. this.request=request;
  15. this.response=response;
  16. this.meta=meta;
  17. }
  18. public Object getAttribute(String name) {
  19. logger.info(getClass()+"getAttribute(),name:"+name);
  20. Jedis jedis =null;
  21. Object obj =null;
  22. String jsonStr = null;
  23. try {
  24. jedis =JedisPoolStore.getInstance().getJedis(meta.getHost(), meta.getPort());
  25. jsonStr = jedis.get(name);
  26. if(jsonStr!=null||StringUtils.isNotEmpty(jsonStr)){
  27. jedis.expire(name, meta.getSeconds());// 重置过期时间
  28. obj =JSON.parseObject(jsonStr, User.class); //反序列对象
  29. }
  30. if (jedis != null) {
  31. JedisPoolStore.getInstance().returnJedis(jedis);
  32. }
  33. return obj;
  34. }
  35. catch (JSONException je) {
  36. logger.error(je.getMessage());
  37. if (null != jedis)
  38. JedisPoolStore.getInstance().returnJedis(jedis);
  39. return jsonStr;
  40. }
  41. catch (Exception e) {
  42. logger.error(e.getMessage());
  43. if (e instanceof JedisException) {
  44. if (null != jedis)
  45. JedisPoolStore.getInstance().returnBrokenJedis(jedis);
  46. } else {
  47. if (null != jedis)
  48. JedisPoolStore.getInstance().returnJedis(jedis);
  49. }
  50. throw new HttpSessionException(" session 异常 getAttribute() name:"+name);
  51. }
  52. }
  53. public void setAttribute(String name, Object value) {
  54. logger.info(getClass()+"setAttribute(),name:"+name);
  55. Jedis jedis =null;
  56. try {
  57. jedis =JedisPoolStore.getInstance().getJedis(meta.getHost(), meta.getPort());
  58. if(value instanceof String){
  59. String value_ =(String) value;
  60. jedis.set(name,value_);//普通字符串对象
  61. }else{
  62. jedis.set(name, JSON.toJSONString(value));//序列化对象
  63. }
  64. jedis.expire(name, meta.getSeconds());// 重置过期时间
  65. if (jedis != null) {
  66. JedisPoolStore.getInstance().returnJedis(jedis);
  67. }
  68. } catch (Exception e) {
  69. logger.error(e.getMessage());
  70. if (e instanceof JedisException) {
  71. if (null != jedis)
  72. JedisPoolStore.getInstance().returnBrokenJedis(jedis);
  73. } else {
  74. if (null != jedis)
  75. JedisPoolStore.getInstance().returnJedis(jedis);
  76. }
  77. throw new HttpSessionException(" session 异常 setAttribute() name:"+name+",value:"+value);
  78. }
  79. }
  80. /**
  81. * 不可用
  82. * @deprecated
  83. *
  84. */
  85. public void invalidate() {
  86. logger.info(getClass()+"invalidate()");
  87. }
  88. public void removeAttribute(String name) {
  89. logger.info(getClass()+"removeAttribute(),name:"+name);
  90. if(StringUtils.isNotEmpty(name)){
  91. Jedis jedis =null;
  92. try {
  93. jedis =JedisPoolStore.getInstance().getJedis(meta.getHost(), meta.getPort());
  94. jedis.del(name);
  95. if (jedis != null) {
  96. JedisPoolStore.getInstance().returnJedis(jedis);
  97. }
  98. } catch (Exception e) {
  99. logger.error(e.getMessage());
  100. if (e instanceof JedisException) {
  101. if (null != jedis)
  102. JedisPoolStore.getInstance().returnBrokenJedis(jedis);
  103. } else {
  104. if (null != jedis)
  105. JedisPoolStore.getInstance().returnJedis(jedis);
  106. }
  107. throw new HttpSessionException(" session 异常 removeAttribute() name:"+name);
  108. }
  109. }
  110. }
  111. /**
  112. * 不可用
  113. * @deprecated
  114. *
  115. */
  116. public Object getValue(String name) {
  117. return null;
  118. }
  119. /**
  120. * 不可用
  121. * @deprecated
  122. *
  123. */
  124. public Enumeration getAttributeNames() {
  125. return null;
  126. }
  127. /**
  128. * 不可用
  129. * @deprecated
  130. *
  131. */
  132. public String[] getValueNames() {
  133. return null;
  134. }
  135. /**
  136. * 不可用
  137. * @deprecated
  138. *
  139. */
  140. public void putValue(String name, Object value) {
  141. }
  142. /**
  143. * 不可用
  144. * @deprecated
  145. *
  146. */
  147. public void removeValue(String name) {
  148. }
  149. public long getCreationTime() {
  150. return creationTime;
  151. }
  152. public String getId() {
  153. logger.info(getClass()+"getId():"+sid);
  154. return sid;
  155. }
  156. public long getLastAccessedTime() {
  157. return lastAccessedTime;
  158. }
  159. /**
  160. * 不可用
  161. * @deprecated
  162. *
  163. */
  164. public ServletContext getServletContext() {
  165. return null;
  166. }
  167. /**
  168. * 不可用
  169. * @deprecated
  170. *
  171. */
  172. public void setMaxInactiveInterval(int interval) {
  173. }
  174. /**
  175. * 不可用
  176. * @deprecated
  177. *
  178. */
  179. public int getMaxInactiveInterval() {
  180. return 0;
  181. }
  182. /**
  183. * 不可用
  184. * @deprecated
  185. *
  186. */
  187. public HttpSessionContext getSessionContext() {
  188. return null;
  189. }
  190. /**
  191. * 不可用
  192. * @deprecated
  193. *
  194. */
  195. public boolean isNew() {
  196. logger.info(getClass()+"isNew()");
  197. return false;
  198. }
  199. }

2.继承HttpServletRequestWrapper

 
  1. /***
  2. *
  3. * @author xiaoshuai
  4. *
  5. */
  6. public class DefinedHttpServletRequestWrapper extends HttpServletRequestWrapper{
  7. protected final Logger logger = LoggerFactory.getLogger(getClass());
  8. private HttpSessionWrapper currentSession;
  9. private HttpServletRequest request;
  10. private HttpServletResponse response;
  11. private String sid = "";
  12. private SessionMeta meta;
  13. public DefinedHttpServletRequestWrapper(HttpServletRequest request) {
  14. super(request);
  15. }
  16. public DefinedHttpServletRequestWrapper(String sid, HttpServletRequest request) {
  17. super(request);
  18. this.sid = sid;
  19. }
  20. public DefinedHttpServletRequestWrapper(String sid, SessionMeta meta,HttpServletRequest request,
  21. HttpServletResponse response) {
  22. super(request);
  23. this.request = request;
  24. this.response = response;
  25. this.sid = sid;
  26. this.meta=meta;
  27. }
  28. @Override
  29. public HttpSession getSession(boolean create) {
  30. if(currentSession != null) {
  31. return currentSession;
  32. }
  33. if(!create) {
  34. return null;
  35. }
  36. currentSession = new HttpSessionWrapper(sid,meta, request, response);
  37. return currentSession;
  38. }
  39. @Override
  40. public HttpSession getSession() {
  41. return getSession(true);
  42. }
  43. }

3.实现filter

 
  1. public class SessionFilter implements Filter{
  2. protected final Logger logger = LoggerFactory.getLogger(getClass());
  3. private static SessionMeta meta = new SessionMeta();
  4. private static final String host ="host";
  5. private static final String port ="port";
  6. private static final String seconds="seconds";
  7. public void init(FilterConfig filterConfig) throws ServletException {
  8. logger.debug("init filterConfig info");
  9. meta.setHost(filterConfig.getInitParameter(host));
  10. meta.setPort(Integer.parseInt(filterConfig.getInitParameter(port)));
  11. meta.setSeconds(Integer.parseInt(filterConfig.getInitParameter(seconds)));
  12. }
  13. public void doFilter(ServletRequest request, ServletResponse response,
  14. FilterChain chain) throws IOException, ServletException {
  15. //从cookie中获取sessionId,如果此次请求没有sessionId,重写为这次请求设置一个sessionId
  16. HttpServletRequest httpRequest = (HttpServletRequest) request;
  17. HttpServletResponse httpResponse = (HttpServletResponse) response;
  18. String sid = CookieHelper.findCookieInfo(httpRequest,CookieHelper.COOKIE_DOMAIN_NAME);
  19. if(StringUtils.isEmpty(sid) ){
  20. try {
  21. sid =CookieHelper.saveCookie(SessionId.doIds(), httpResponse);
  22. } catch (Exception e) {
  23. e.printStackTrace();
  24. }
  25. }
  26. logger.info("JESSIONID:"+sid);
  27. chain.doFilter(new DefinedHttpServletRequestWrapper(sid,meta,httpRequest, httpResponse), response);
  28. }
  29. public void destroy() {
  30. }
  31. }

4.配置web.xml

 
  1. <!-- session过滤器 -->
  2. <filter>
  3. <filter-name>sessionFilter</filter-name>
  4. <filter-class>cn.session.filter.SessionFilter</filter-class>
  5. <init-param>
  6. <param-name>host</param-name>
  7. <param-value>10.1.193.1</param-value>
  8. </init-param>
  9. <init-param>
  10. <param-name>port</param-name>
  11. <param-value>6372</param-value>
  12. </init-param>
  13. <init-param>
  14. <param-name>seconds</param-name>
  15. <param-value>1800</param-value>
  16. </init-param>
  17. </filter>
  18. <filter-mapping>
  19. <filter-name>sessionFilter</filter-name>
  20. <url-pattern>/*</url-pattern>
  21. </filter-mapping>

第六种:(没用过,感觉这个人的挺靠谱,直接粘贴过来了,参考博客的地址也在最上面)

 
  1. 这里简单记录下整合的过程:
  2. 如果项目之前没有整合过spring-data-redis的话,这一步需要先做,在maven中添加这两个依赖:
  3. <dependency>
  4. <groupId>org.springframework.data</groupId>
  5. <artifactId>spring-data-redis</artifactId>
  6. <version>1.5.2.RELEASE</version>
  7. </dependency>
  8. <dependency>
  9. <groupId>org.springframework.session</groupId>
  10. <artifactId>spring-session</artifactId>
  11. <version>1.0.2.RELEASE</version>
  12. </dependency>
  13. 再在applicationContext.xml中添加以下bean,用于定义redis的连接池和初始化redis模版操作类,自行替换其中的相关变量。
  14. <!-- redis -->
  15. <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
  16. </bean>
  17. <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
  18. <property name="hostName" value="${redis.host}" />
  19. <property name="port" value="${redis.port}" />
  20. <property name="password" value="${redis.pass}" />
  21. <property name="timeout" value="${redis.timeout}" />
  22. <property name="poolConfig" ref="jedisPoolConfig" />
  23. <property name="usePool" value="true" />
  24. </bean>
  25. <bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
  26. <property name="connectionFactory" ref="jedisConnectionFactory" />
  27. </bean>
  28. <!-- 将session放入redis -->
  29. <bean id="redisHttpSessionConfiguration" class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration">
  30. <property name="maxInactiveIntervalInSeconds" value="1800" />
  31. </bean>
  32. 这里前面几个bean都是操作redis时候使用的,最后一个bean才是spring-session需要用到的,其中的id可以不写或者保持不变,这也是一个约定优先配置的体现。这个bean中又会自动产生多个bean,用于相关操作,极大的简化了我们的配置项。其中有个比较重要的是springSessionRepositoryFilter,它将在下面的代理filter中被调用到。maxInactiveIntervalInSeconds表示超时时间,默认是1800秒。写上述配置的时候我个人习惯采用xml来定义,官方文档中有采用注解来声明一个配置类。
  33. 然后是在web.xml中添加一个session代理filter,通过这个filter来包装Servlet的getSession()。需要注意的是这个filter需要放在所有filter链最前面。
  34. <!-- delegatingFilterProxy -->
  35. <filter>
  36. <filter-name>springSessionRepositoryFilter</filter-name>
  37. <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
  38. </filter>
  39. <filter-mapping>
  40. <filter-name>springSessionRepositoryFilter</filter-name>
  41. <url-pattern>/*</url-pattern>
  42. </filter-mapping>
  43. 这样便配置完毕了,需要注意的是,spring-session要求Redis Server版本不低于2.8。
  44. 验证:使用redis-cli就可以查看到session key了,且浏览器Cookie中的jsessionid已经替换为session。
  45. 127.0.0.1:6379> KEYS *
  46. 1) "spring:session:expirations:1440922740000"
  47. 2) "spring:session:sessions:35b48cb4-62f8-440c-afac-9c7e3cfe98d3"

第七种:如果项目中用到shiro了,shiro是不带将session持久化到redis实现集群共享的,所以说需要自己实现或者找别人写好的,下面来说说自己实现,不管别人写还是自己实现思路都是一样的,了解了岂不是更好。(这个自己项目确实遇到这个问题了,通过网上的资料已经解决,参考的太多就不贴地址了,只说自己怎么弄的)

 
  1. 配置shiro的xml
  2. <!-- SessionManager -->
  3. <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
  4. <!-- session存储的实现(此处为自己重写的sessionDao) -->
  5. <property name="sessionDAO" ref="redisSessionDAO" />
  6. <!-- 定时清理失效会话, 清理用户直接关闭浏览器造成的孤立会话 -->
  7. <property name="sessionValidationInterval" value="1800000"/>
  8. <property name="sessionValidationSchedulerEnabled" value="true"/>
  9. <property name="sessionIdCookie" ref="sessionIdCookie"/>
  10. <property name="sessionIdCookieEnabled" value="true"/>
  11. </bean>

RedisSessionDao

 
  1. public class RedisSessionDao extends AbstractSessionDAO {
  2. private static Logger logger = LoggerFactory.getLogger(RedisSessionDao.class);
  3. /*
  4. * The Redis key prefix for the sessions
  5. */
  6. private static final String REDIS_SHIRO_SESSION = "shiro_redis_session:";
  7. private static final Integer SESSION_VAL_TIME_SPAN = 18000;
  8. /**
  9. * redis接口
  10. */
  11. @Resource(name = "cacheServiceImpl")
  12. private ICacheService iCacheService;
  13. /**
  14. * @discription 创建session,保存到数据库
  15. *
  16. * @param session
  17. * @return
  18. *
  19. * @author zhaoqiang
  20. * @created 2017年3月3日 下午1:28:09
  21. */
  22. @Override
  23. protected Serializable doCreate(Session session) {
  24. Serializable sessionId = this.generateSessionId(session);
  25. this.assignSessionId(session, sessionId);
  26. saveSession(session);
  27. return sessionId;
  28. }
  29. /**
  30. * @discription 获取session
  31. *
  32. * @param sessionId
  33. * @return
  34. *
  35. * @author zhaoqiang
  36. * @created 2017年3月3日 下午1:28:43
  37. */
  38. @Override
  39. protected Session doReadSession(Serializable sessionId) {
  40. if (sessionId == null) {
  41. throw new NullPointerException("session id is empty");
  42. }
  43. SimpleSession session = null;
  44. try {
  45. byte[] value = iCacheService.getByte(buildRedisSessionKey(sessionId));
  46. session = SerializeUtil.unserialize(value, SimpleSession.class);
  47. } catch (Exception e) {
  48. e.printStackTrace();
  49. logger.error("get session error");
  50. }
  51. return session;
  52. }
  53. /**
  54. * @discription 更新session的最后一次访问时间
  55. *
  56. * @param session
  57. *
  58. * @author zhaoqiang
  59. * @created 2017年3月3日 下午1:34:24
  60. */
  61. @Override
  62. public void update(Session session) {
  63. saveSession(session);
  64. }
  65. /**
  66. * @discription 删除session
  67. *
  68. * @param session
  69. *
  70. * @author zhaoqiang
  71. * @created 2017年3月3日 下午1:35:48
  72. */
  73. @Override
  74. public void delete(Session session) {
  75. if (session == null) {
  76. logger.error("session can not be null,delete failed");
  77. return;
  78. }
  79. Serializable id = session.getId();
  80. if (id == null) {
  81. throw new NullPointerException("session id is empty");
  82. }
  83. try {
  84. iCacheService.delByString(buildRedisSessionKey(id));
  85. } catch (Exception e) {
  86. e.printStackTrace();
  87. logger.error("delete session error");
  88. }
  89. }
  90. /**
  91. * @discription 获得活跃的session集合
  92. *
  93. * @return
  94. *
  95. * @author zhaoqiang
  96. * @created 2017年3月3日 下午2:05:22
  97. */
  98. @Override
  99. public Collection<Session> getActiveSessions() {
  100. Set<Session> sessions = new HashSet<Session>();
  101. try {
  102. Set<String> keys = iCacheService.keys(REDIS_SHIRO_SESSION);
  103. if (keys == null || keys.size() == 0) {
  104. return sessions;
  105. }
  106. for (String key : keys) {
  107. Session s = null;
  108. try {
  109. s = iCacheService.getObject(key, SimpleSession.class);
  110. } catch (ClassNotFoundException e) {
  111. e.printStackTrace();
  112. } catch (IOException e) {
  113. e.printStackTrace();
  114. }
  115. sessions.add(s);
  116. }
  117. } catch (Exception e) {
  118. logger.error("[获得活跃的session集合(getActiveSessions)-error][" + e.getMessage() + "]");
  119. e.printStackTrace();
  120. }
  121. return sessions;
  122. }
  123. /**
  124. * @discription 处理缓存中id名称
  125. *
  126. * @param sessionId
  127. * @return
  128. *
  129. * @author zhaoqiang
  130. * @created 2017年3月9日 下午1:13:45
  131. */
  132. private String buildRedisSessionKey(Serializable sessionId) {
  133. return REDIS_SHIRO_SESSION + sessionId;
  134. }
  135. /**
  136. * @discription 持久化session到redis
  137. *
  138. * @param session
  139. *
  140. * @author zhaoqiang
  141. * @created 2017年3月9日 下午1:06:53
  142. */
  143. private void saveSession(Session session) {
  144. if (session == null || session.getId() == null) {
  145. throw new NullPointerException("session is empty");
  146. }
  147. try {
  148. String key = buildRedisSessionKey(session.getId());
  149. long sessionTimeOut = session.getTimeout() / 1000;
  150. Long expireTime = sessionTimeOut + SESSION_VAL_TIME_SPAN + (5 * 60);
  151. iCacheService.setObject(key, session, new Integer(expireTime.toString()));
  152. } catch (Exception e) {
  153. e.printStackTrace();
  154. logger.error("save session error");
  155. }
  156. }
  157. }
public class HttpSessionWrapper implements HttpSession {
  protected final Logger logger = LoggerFactory.getLogger(getClass());
   private String sid = "";
   private HttpServletRequest request;
   private HttpServletResponse response;
   private final long creationTime = System.currentTimeMillis();
   private final long lastAccessedTime = System.currentTimeMillis();
   private SessionMeta meta;
   public HttpSessionWrapper() {
   }
  public HttpSessionWrapper(String sid,SessionMeta meta, HttpServletRequest request,
       HttpServletResponse response) {
     this.sid=sid;
     this.request=request;
     this.response=response;
     this.meta=meta;
   }
   public Object getAttribute(String name) {
     logger.info(getClass()+"getAttribute(),name:"+name);
      Jedis jedis =null;
      Object obj =null;
      String jsonStr = null;
     try {
       jedis =JedisPoolStore.getInstance().getJedis(meta.getHost(), meta.getPort());
       jsonStr = jedis.get(name);
       if(jsonStr!=null||StringUtils.isNotEmpty(jsonStr)){
         jedis.expire(name, meta.getSeconds());// 重置过期时间
         obj =JSON.parseObject(jsonStr, User.class); //反序列对象
       }
       if (jedis != null) {
         JedisPoolStore.getInstance().returnJedis(jedis);
       }
       return obj;
     } 
     catch (JSONException je) {
       logger.error(je.getMessage());
         if (null != jedis)
           JedisPoolStore.getInstance().returnJedis(jedis);
       return jsonStr;
     }
     catch (Exception e) {
       logger.error(e.getMessage());
       if (e instanceof JedisException) {
         if (null != jedis)
           JedisPoolStore.getInstance().returnBrokenJedis(jedis);
       } else {
         if (null != jedis)
           JedisPoolStore.getInstance().returnJedis(jedis);
       }
       throw new HttpSessionException(" session 异常  getAttribute() name:"+name);
     }
  }
  public void setAttribute(String name, Object value) {
     logger.info(getClass()+"setAttribute(),name:"+name);
     Jedis jedis =null;
     try {
       jedis =JedisPoolStore.getInstance().getJedis(meta.getHost(), meta.getPort());
       if(value instanceof String){
         String value_ =(String) value;
         jedis.set(name,value_);//普通字符串对象
       }else{
         jedis.set(name, JSON.toJSONString(value));//序列化对象
       }
       

       jedis.expire(name, meta.getSeconds());// 重置过期时间
       if (jedis != null) {
         JedisPoolStore.getInstance().returnJedis(jedis);
       }
     } catch (Exception e) {
       logger.error(e.getMessage());
       if (e instanceof JedisException) {
         if (null != jedis)
           JedisPoolStore.getInstance().returnBrokenJedis(jedis);
       } else {
         if (null != jedis)
           JedisPoolStore.getInstance().returnJedis(jedis);
       }
       throw new HttpSessionException(" session 异常  setAttribute() name:"+name+",value:"+value);
     }

  }
  /**
   \* 不可用
   \* @deprecated
   \* 
   */
  public void invalidate() {
     logger.info(getClass()+"invalidate()");
  }

  public void removeAttribute(String name) {
     logger.info(getClass()+"removeAttribute(),name:"+name);
     if(StringUtils.isNotEmpty(name)){
       Jedis jedis =null;
       try {
         jedis =JedisPoolStore.getInstance().getJedis(meta.getHost(), meta.getPort());
         jedis.del(name);
         if (jedis != null) {
           JedisPoolStore.getInstance().returnJedis(jedis);
         }
       } catch (Exception e) {
         logger.error(e.getMessage());
         if (e instanceof JedisException) {
           if (null != jedis)
             JedisPoolStore.getInstance().returnBrokenJedis(jedis);
         } else {
           if (null != jedis)
             JedisPoolStore.getInstance().returnJedis(jedis);
         }
         throw new HttpSessionException(" session 异常  removeAttribute() name:"+name);
       }
     }

  }
  /**
   \* 不可用
   \* @deprecated
   \* 
   */
  public Object getValue(String name) {
    return null;
  }
  /**
   \* 不可用
   \* @deprecated
   \* 
   */
  public Enumeration getAttributeNames() {
     return  null;

  }       
  /**
   \* 不可用
   \* @deprecated
   \* 
   */
  public String[] getValueNames() {
     return  null;   
   }
  /**
   \* 不可用
   \* @deprecated
   \* 
   */
  public void putValue(String name, Object value) {
  }
  /**
   \* 不可用
   \* @deprecated
   \* 
   */
  public void removeValue(String name) {
  }

  public long getCreationTime() {
     return  creationTime;
  }

  public String getId() {
     logger.info(getClass()+"getId():"+sid);
    return sid;
  }

  public long getLastAccessedTime() {
    return lastAccessedTime;
  }
  /**
   \* 不可用
   \* @deprecated
   \* 
   */
  public ServletContext getServletContext() {
    return null;
  }
  /**
   \* 不可用
   \* @deprecated
   \* 
   */
  public void setMaxInactiveInterval(int interval) {
  }
  /**
   \* 不可用
   \* @deprecated
   \* 
   */
  public int getMaxInactiveInterval() {
    return 0;
  }
  /**
   \* 不可用
   \* @deprecated
   \* 
   */
  public HttpSessionContext getSessionContext() {
    return null;
  }
  /**
   \* 不可用
   \* @deprecated
   \* 
   */
  public boolean isNew() {
     logger.info(getClass()+"isNew()");
    return false;
  }
}