HttpSession是通过Servlet容器创建和管理的,像Tomcat/Jetty都是保存在内存中的。但是把应用搭建成分布式的集群,然后利用F5、LVS或Nginx做负载均衡,那么来自同一用户的Http请求将有可能被分发到多个不同的服务器中。那问题来了,如何保证不同的服务器能够共享同一份session数据呢?最简单的想法,就是把session数据保存到内存以外的一个统一的地方,例如Memcached/Redis等数据库中。那问题又来了,如何替换掉Servlet容器创建和管理的HttpSession的实现呢?

方案一:利用Servlet容器提供的插件功能,自定义HttpSession的创建和管理策略,并通过配置的方式替换掉默认的策略。这方面其实早就有开源项目了,例如memcached-session-manager(可以参考负载均衡+session共享(memcached-session-manager实现),以及tomcat-redis-session-manager。不过这种方式有个缺点,就是需要耦合Tomcat/Jetty等Servlet容器的代码。

方案二:设计一个Filter,利用HttpServletRequestWrapper,实现自己的 getSession()方法,接管创建和管理Session数据的工作。spring-session就是通过这样的思路实现的。

分布式session_分布式session问题_分布式session是什么

1、新建项目sc-redis-session,对应的pom.xml文件如下

 
 4.0.0
 spring-cloud
 sc-redis-session
 0.0.1-SNAPSHOT
 jar
 sc-redis-session
 http://maven.apache.org
 
 org.springframework.boot
 spring-boot-starter-parent
 2.0.4.RELEASE
 
 
 
 
 org.springframework.cloud
 spring-cloud-dependencies
 Finchley.RELEASE
 pom
 import
 
 
 
 
 UTF-8
 1.8
 1.8
 
 
 
 org.springframework.boot
 spring-boot-starter-data-redis
 
 
 org.apache.commons
 commons-pool2
 
 
 org.springframework.boot
 spring-boot-starter-web
 
 
 org.springframework.session
 spring-session-data-redis
 
 
 com.alibaba
 fastjson
 1.2.49
 
 

2、新建springboot启动类RedisSessionApplication.java

package com.redis.session;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
@SpringBootApplication
@EnableRedisHttpSession
public class RedisSessionApplication {
 public static void main(String[] args) {
 SpringApplication.run(RedisSessionApplication.class, args);
 }
}

说明:主要使用EnableRedisHttpSession注解开启spring分布式session,该类的作用是配置org.springframework.session.web.http.SessionRepositoryFilter进行请求拦截

3、新建配置文件application.yml

 server:
 port: 7200
spring:
 session:
 store-type: redis
 application:
 name: sc-redis-session
 redis:
 host: 127.0.0.1
 password: 
 port: 6379
 timeout: 10000 # 连接超时时间(毫秒)
 database: 0 # Redis默认情况下有16个分片,这里配置具体使用的分片,默认是0
 lettuce:
 pool:
 max-active: 8 # 连接池最大连接数(使用负值表示没有限制) 默认 8
 max-wait: -1 # 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1
 max-idle: 8 # 连接池中的最大空闲连接 默认 8
 min-idle: 0 # 连接池中的最小空闲连接 默认 0

4、 新建一个UserController

package com.redis.session.controller;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import com.alibaba.fastjson.JSON;
import com.redis.session.model.User;
@RestController
public class UserController {
 private static final Logger logger = LoggerFactory.getLogger(UserController.class);
 /**
 * 把用户放入session
 * 
 * @param request
 * @return
 */
 @RequestMapping("/user/login")
 @ResponseBody
 public Map login(HttpServletRequest request) {
 // 取出session中的userName
 Object loginUser = request.getSession().getAttribute("loginUser");
 if (loginUser == null) {
 logger.info("不存在session,设置user");
 User u = new User();
 u.setAge(23);
 u.setId(1L);
 u.setPosition("总裁");
 u.setUserName("huangjinjin");
 request.getSession().setAttribute("loginUser", u);
 } else {
 logger.info("存在session,user=" + JSON.toJSONString(loginUser));
 }
 Cookie[] cookies = request.getCookies();
 if (cookies != null && cookies.length > 0) {
 for (Cookie cookie : cookies) {
 logger.info(cookie.getName() + " : " + cookie.getValue());
 }
 }
 Map resp = new HashMap();
 resp.put("code", "000000");
 resp.put("msg", "交易成功");
 return resp;
 }
 /**
 * 获取session的用户
 * 
 * @param request
 * @return
 */
 @RequestMapping("/user/getUser")
 @ResponseBody
 public Map getUser(HttpServletRequest request) {
 Map resp = new HashMap();
 resp.put("code", "000000");
 resp.put("msg", "交易成功");
 resp.put("body", request.getSession().getAttribute("loginUser"));
 Cookie[] cookies = request.getCookies();
 if (cookies != null && cookies.length > 0) {
 for (Cookie cookie : cookies) {
 logger.info(cookie.getName() + " : " + cookie.getValue());
 }
 }
 return resp;
 }
}

5、启动项目,查看日志是否启动成功

分布式session_分布式session问题_分布式session是什么

6、使用谷歌浏览器访问接口

第一次访问登录接口::7200/user/login

分布式session是什么_分布式session问题_分布式session

控制台打印:

分布式session_分布式session是什么_分布式session问题

第二次至第n次:控制台打印

分布式session问题_分布式session_分布式session是什么

访问获取session接口:返回对应的用户数据

分布式session_分布式session问题_分布式session是什么

7、通过reids客户端redis-cli查看redis服务器的数据

限 时 特 惠: 本站每日持续更新海量各大内部创业教程,一年会员只需98元,全站资源免费下载 点击查看详情
站 长 微 信: lzxmw777

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注