文章目录
Spring Session介绍
在默认情况下,SpringBoot使用Tomcat服务器的Session实现,编写一个例子测试:
@RestController
@RequestMapping("/session")
@Slf4j
public class SpringSessionController {
@RequestMapping("/putsession")
public String putSession(HttpServletRequest request) {
HttpSession session = request.getSession();
log.info("sessionClass为:{}", session.getClass());
log.info("sessionId为:{}", session.getId());
session.setAttribute("user", "i am leo825");
return "putsession success";
}
}
通过访问:http://localhost:8080/springsession-demo/session/putsession,控制台输出为:
2021-01-13 23:18:53.853 [http-nio-8080-exec-1] INFO com.demo.controller.SpringSessionController:19 - sessionClass为:class org.apache.catalina.session.StandardSessionFacade
2021-01-13 23:18:53.854 [http-nio-8080-exec-1] INFO com.demo.controller.SpringSessionController:20 - sessionId为:23813E88BC0FA799EB883F3D23F9CB15
可以看到,Session管理是通过Tomcat提供的class org.apache.catalina.session.StandardSessionFacade
实现的,
配置文件yml中添加如下内容:
spring:
session:
store-type: redis
其中,spring.session.store-type有以下值:
- redis :Sessio数据存放Redis中。
- jdbc:会话数据存放在数据库中,默认情况下SPRING_SESSION表存放Session基本信息,如sessionId、创建时间、最后一次访问时间等,SPRING_SESSION_ATTRIBUTES表存放了session数据,ATTRIBUTE_NAME列保存了Session的Key,ATTRIBUTE_BYTES列以字节形式存放了Session的Value,Spring Session会自动创建这两张表。
- hazelcast:Session数据存放到Hazelcast。
- None:禁用Spring Session功能。
Redis集成
yml配置
springboot集成Redis可以参考《SpringBoot笔记:SpringBoot2.3集成Redis Cluster集群配置》
这里就添加如下配置,使用redis存储session:
spring:
session:
store-type: redis
依赖添加
在引入spring-boot-starter-data-redis的依赖的同时,添加spring-session-data-redis依赖
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
redis存值查看
测试代码仍然是上面的测试代码,现在进行测试。启动项目,并访问http://localhost:8080/springsession-demo/session/putsession,控制台输出为:
2021-01-13 23:35:55.827 [http-nio-8080-exec-1] INFO o.a.c.c.C.[.[localhost].[/springsession-demo]:173 - Initializing Spring DispatcherServlet 'dispatcherServlet'
2021-01-13 23:35:55.910 [http-nio-8080-exec-1] INFO com.demo.controller.SpringSessionController:19 - sessionClass为:class org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper$HttpSessionWrapper
2021-01-13 23:35:55.911 [http-nio-8080-exec-1] INFO com.demo.controller.SpringSessionController:20 - sessionId为:31115fe8-2169-4099-879f-090fbb6edc44
登录服务器查看redis的值
redis-cli -c -p 7001 -a admin@2021
查询所有”spring:session:”开头的keys
keys spring:session:*
输出结果如下:
192.168.223.131:7003> keys spring:session:*
1) "spring:session:expirations:1610553960000"
2) "spring:session:sessions:expires:31115fe8-2169-4099-879f-090fbb6edc44"
会话信息存放在”spring:session:sessions:”开头的key中,31115fe8-2169-4099-879f-090fbb6edc44代表一个会话id,”spring:session:sessions:31115fe8-2169-4099-879f-090fbb6edc44″是一个Hash数据结构,可以用Redis HASH相关命令来查看数据:
hgetall "spring:session:sessions:31115fe8-2169-4099-879f-090fbb6edc44"
输出结果如下:
192.168.223.131:7003> hgetall "spring:session:sessions:31115fe8-2169-4099-879f-090fbb6edc44"
-> Redirected to slot [5335] located at 192.168.223.131:7001
1) "maxInactiveInterval"
2) "\xac\xed\x00\x05sr\x00\x11java.lang.Integer\x12\xe2\xa0\xa4\xf7\x81\x878\x02\x00\x01I\x00\x05valuexr\x00\x10java.lang.Number\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x00xp\x00\x00\a\b"
3) "creationTime"
4) "\xac\xed\x00\x05sr\x00\x0ejava.lang.Long;\x8b\xe4\x90\xcc\x8f#\xdf\x02\x00\x01J\x00\x05valuexr\x00\x10java.lang.Number\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x00xp\x00\x00\x01v\xfc?\xc5\xcd"
5) "lastAccessedTime"
6) "\xac\xed\x00\x05sr\x00\x0ejava.lang.Long;\x8b\xe4\x90\xcc\x8f#\xdf\x02\x00\x01J\x00\x05valuexr\x00\x10java.lang.Number\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x00xp\x00\x00\x01v\xfcc\x9e\xe9"
7) "sessionAttr:user"
8) "\xac\xed\x00\x05t\x00\x0bi am leo825"
使用以下命令查看Session中user的信息:
HMGET "spring:session:sessions:31115fe8-2169-4099-879f-090fbb6edc44" sessionAttr:user
输出结果:
192.168.223.131:7001> HMGET "spring:session:sessions:31115fe8-2169-4099-879f-090fbb6edc44" sessionAttr:user
1) "\xac\xed\x00\x05t\x00\x0bi am leo825"
SpringBoot默认创建的key
上面的例子中sessionAttr:user是Spring Session 中存入Redis的key值,sessionAttr:是其前缀,user是我们在会话中设置的key,其他SpringBoot默认创建的key有:
- creationTime,创建时间
- maxInactiveInterval,指定过期时间(秒)
- lastAccessedTime,上次访问时间。
- sessionAttr,以“sessionAttr:”为前缀的会话信息,比如:sessionAttr:user.
注意:
Spring Session 的Redis实现并不是每次通过Session类获取会话信息或者保存的时候都会调用Redis操作,它会先尝试从内部HashMap读取值,如果没有,才调用Redis的HMGET操作。同样,当保存会话的时候也没有立即调用Redis操作,二十先保存到HashMap中,等待服务请求结束后在即将变化的值使用HMSET更新。如果你项在保存会话操作后立即更新到Redis中,需要配置成IMMEDIATE模式,配置如下:
spring.session.redis.flushMode=IMMEDIATE
前面我们可以看到这个key
"spring:session:sessions:expires:31115fe8-2169-4099-879f-090fbb6edc44"
着是因为Redis会话国企并没有直接使用在session:sessions:key变量上,而是专门在session:sessions:expires:key上,当此Key过期后,会自动清除对应的会话信息。可以使用ttl命令查看过期时间:
ttl "spring:session:sessions:expires:31115fe8-2169-4099-879f-090fbb6edc44"
输出结果如下:
192.168.223.131:7001> ttl "spring:session:sessions:expires:31115fe8-2169-4099-879f-090fbb6edc44"
-> Redirected to slot [14958] located at 192.168.223.131:7003
(integer) 269
还有269秒就过期了
nginx集成
可以先参考《CentOS7下安装nginx1.99》文章中nginx配置
其中nginx配置如下:
# nginx的upstream配置,采用轮询配置
upstream bakend {
server hadoop-master:8001;
server hadoop-master:8002;
server hadoop-master:8003;
}
sever中添加我们的上下文路径:
# springboot-session测试项目
location /springsession-demo {
proxy_pass http://bakend;
}
我们这里使用三台机器模拟集群情况。将我们的测试代码达成jar包,然后在服务器上启动:
nohup java -jar springboot-session-1.0-SNAPSHOT.jar --server.port=8001 &
nohup java -jar springboot-session-1.0-SNAPSHOT.jar --server.port=8002 &
nohup java -jar springboot-session-1.0-SNAPSHOT.jar --server.port=8003 &
访问nginx测试地址:http://hadoop-master/springsession-demo/session/putsession,访问3次,可以看到3个服务器的开始轮询输出以下日志:
2021-01-14 00:21:49.280 [http-nio-8003-exec-1] INFO o.a.c.c.C.[.[localhost].[/springsession-demo]:173 - Initializing Spring DispatcherServlet 'dispatcherServlet'
2021-01-14 00:21:49.568 [http-nio-8003-exec-1] INFO com.demo.controller.SpringSessionController:19 - sessionClass为:class org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper$HttpSessionWrapper
2021-01-14 00:21:49.569 [http-nio-8003-exec-1] INFO com.demo.controller.SpringSessionController:20 - sessionId为:425dead7-57b0-4552-a1fe-774b1e11184d
如果停掉其中一台服务,这里把端口为8003的停掉了:
[root@hadoop-master springboot-port8003]# ps -ef|grep springboot-session-1.0-SNAPSHOT.jar
root 4318 3340 2 00:11 pts/1 00:00:19 java -jar springboot-session-1.0-SNAPSHOT.jar --server.port=8003
root 4363 3340 3 00:12 pts/1 00:00:22 java -jar springboot-session-1.0-SNAPSHOT.jar --server.port=8002
root 4384 3340 3 00:12 pts/1 00:00:23 java -jar springboot-session-1.0-SNAPSHOT.jar --server.port=8001
root 4734 4521 0 00:24 pts/3 00:00:00 grep --color=auto springboot-session-1.0-SNAPSHOT.jar
[root@hadoop-master springboot-port8003]# kill -9 4318
[root@hadoop-master springboot-port8003]# ps -ef|grep springboot-session-1.0-SNAPSHOT.jar
root 4363 3340 3 00:12 pts/1 00:00:22 java -jar springboot-session-1.0-SNAPSHOT.jar --server.port=8002
root 4384 3340 3 00:12 pts/1 00:00:23 java -jar springboot-session-1.0-SNAPSHOT.jar --server.port=8001
root 4736 4521 0 00:24 pts/3 00:00:00 grep --color=auto springboot-session-1.0-SNAPSHOT.jar
然后继续访问nginx测试地址:http://hadoop-master/springsession-demo/session/putsession,发现服务仍能够正常运行,因为session信息存在于redis中对于3台机器都是共享的。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/72627.html