导航目录
- 楔子
- session 共享问题解决
- 1 session复制
- 2 hash一致性
- 3 统一存储
- 4 session共享问题解决-不同服务,子域session共享|(springSession)
- SpringSession 简单使用
- 1 pom引入依赖
- 2 使用注解开启 springsession
- 3 配置文件
- 遇到的问题
楔子
学习笔记 ,做个记录
session 共享问题解决
1 session复制
- 优点
tomcat 原生支持,只需要修改配置文件 - 缺点
- session 同步需要数据传输,占用大量网络带宽,降低了服务器群的业务处理能力
- 任意一台web-server保存的数据都是所有web-server的session总和,收到内存限制无法水平扩展更多的web-server
- 大型分布式集群情况下,由于所有web-server都全量保存数据,所有次方案不可取
2 hash一致性
- 优点
- 只需要该nginx配置,不需要修改应用代码
- 负载均衡,只要hash属性的值分布式均匀的,多台web-server的负载是均衡的
- 可以支持web-server水平扩展(session同步是不行的,受内存限制)
- 缺点
- session还是存在web-server中,所有web-server重启可能导致session丢失,影响业务,如部分用户需要重新登录。
- 如果web-server水平扩展,rehash后的session重新分布,也会有一部分用户路由到不正确的session。
以上的缺点问题不大,因为session本来都是有有效期的。所有这两种反向代理的方式可以使用。
3 统一存储
- 优点
- 没有安全隐患
- 可以水平扩展,数据库/缓存水平切分即可
- web-server重启或扩容都不会丢失
- 不足
- 增加了一次网络调用,并且需要修改相应的代码,如将所有的getSession方法替换为从Redis查数据的方式,redis获取数据比内存慢很多。
- 上面的缺点可以用springSession完美解决。
4 session共享问题解决-不同服务,子域session共享|(springSession)
SpringSession 简单使用
以下使用Redis作为存储session的介质
1 pom引入依赖
<!-- springSession -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2 使用注解开启 springsession
# springboot启动类加注解
@EnableRedisHttpSession
代码中处理
@Slf4j
@RestController
@RequestMapping("/session")
public class SessionController {
@RequestMapping("login")
public String login(HttpServletRequest req, HttpServletResponse resp, HttpSession session,
User user) {
//TODO 1 默认发的令牌,SESSION=*** ,作用域:当前域(解决子域共享)
//TODO 2使用JSON的序列化存储数据到 Redis
log.info("login user is {}", user);
session.setAttribute(SysUtils.LOGIN_NAME, user);
return String.format("%s|%s|", SysUtils.getDateSpan(), user.getUname());
}
@RequestMapping("show")
public Object showLoginUser(HttpSession session) {
Object attribute = session.getAttribute(SysUtils.LOGIN_NAME);
log.info("获取的session user is {}", JSON.toJSONString(attribute));
return attribute;
}
}
设置Redis存储为JSON以及配置子域共享
@Configuration
public class SessionConfig {
/**
* 设置热session cookie name 以及子域共享
*
* @return
*/
@Bean
public CookieSerializer cookieSerializer() {
DefaultCookieSerializer serializer = new DefaultCookieSerializer();
serializer.setCookieName("WEBJSESSIONID");
serializer.setCookiePath("/");
serializer.setDomainName("grq.com");
//serializer.setDomainNamePattern("^.+?\\.(\\w+\\.[a-z]+)$");
return serializer;
}
/**
* 设置redis session 序列化方式为JSON
*
* @return
*/
@Bean
public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
//return new FastJsonRedisSerializer();
//return new GenericFastJsonRedisSerializer();
return new GenericJackson2JsonRedisSerializer();
}
}
**域名和子域名使用Windows hosts模拟 **
3 配置文件
配置存储方式为redis,以及redis配置
################################ session
spring.session.store-type=redis
# more就是30分钟
server.servlet.session.timeout=30m
################################ session |end
#redis
spring.redis.host=127.0.0.1
spring.redis.port=6379
Redis存储
**域名 使用SwitchHosts! 添加模拟 **
遇到的问题
使用fastjson 作为序列化 JSON的时候,出现了**NoSuchMethodError: com.alibaba.fastjson.serializer.JavaBeanSerializer.processValue**
https:///alibaba/fastjson/issues/2780 需要升级 将fastjson从1.2.57升级到1.2.61