一,为什么要使用分布式session?
HpptSession默认使用内存来管理Session,如果将应用横向扩展将会出现Session共享问题,
所以我们在创建web集群时,把session保存到redis中,
这样用户访问到web集群中的任一台服务器,都可以读取到自己的session信息
说明:刘宏缔的架构森林是一个专注架构的博客,地址:https://www.cnblogs.com/architectforest
对应的源码可以访问这里获取: https://github.com/liuhongdi/
说明:作者:刘宏缔 邮箱: 371125307@qq.com
二,演示项目相关信息
1,项目地址:
https://github.com/liuhongdi/redissession
2,项目原理
把session保存到redis中,从而实现分布式的session
为了防止单点问题,我们首先要创建一个redis cluster
3,redis cluster结构
redis1: 172.17.0.2
redis2: 172.17.0.3
redis3: 172.17.0.4
redis4: 172.17.0.5
redis5: 172.17.0.6
redis6: 172.17.0.7
4,项目结构:
如图:
三,创建redis cluster
1,每台机器:生成安装用目录:
[root@redis /]# mkdir /usr/local/soft [root@redis /]# mkdir /usr/local/source [root@redis /]# mkdir /usr/local/source/redis
2,每台机器:安装必需的rpm包
[root@redis redis]# dnf install wget [root@redis redis]# dnf install gcc [root@redis redis]# dnf install tcl [root@redis redis]# dnf install make [root@redis redis]# dnf install which
3,每台机器:下载/编译/安装:
[root@redis /]# cd /usr/local/source/redis/ [root@redis redis]# wget http://download.redis.io/releases/redis-6.0.5.tar.gz
[root@redis redis]# tar -zxvf redis-6.0.5.tar.gz
编译、安装
[root@redis redis]# cd redis-6.0.5 [root@redis redis-6.0.5]# make PREFIX=/usr/local/soft/redis-6.0.5 install
[root@redis redis-6.0.5]# make test
o/ All tests passed without errors!
4,每台机器:配置
[root@redis redis-6.0.5]# mkdir /usr/local/soft/redis-6.0.5/conf [root@redis redis-6.0.5]# cp redis.conf /usr/local/soft/redis-6.0.5/conf/
生成日志/数据目录
[root@redis redis-6.0.5]# mkdir -p /data/redis-6.0.5/logs [root@redis redis-6.0.5]# mkdir -p /data/redis-6.0.5/data [root@redis redis-6.0.5]# mkdir -p /data/redis-6.0.5/cluster
[root@redis redis-6.0.5]# cd /usr/local/soft/redis-6.0.5/conf/ [root@redis conf]# vi redis.conf
配置项内容:
daemonize yes logfile "/data/redis-6.0.5/logs/redis.log" maxmemory 128MB dir /data/redis-6.0.5/data/ protected-mode no requirepass lhddemo #bind 127.0.0.1(此行注释掉) io-threads 2 cluster-enabled yes(此行取消注释) cluster-config-file /data/redis-6.0.5/cluster/nodes-6379.conf cluster-node-timeout 15000(此行取消注释) masterauth lhddemo
5,每台机器:用systemd管理redis服务
生成服务文件
[root@redis conf]# vi /lib/systemd/system/redis6.service
[Unit] Description=Redis After=network.target [Service] Type=forking PIDFile=/var/run/redis_6379.pid ExecStart=/usr/local/soft/redis-6.0.5/bin/redis-server /usr/local/soft/redis-6.0.5/conf/redis.conf ExecReload=/bin/kill -s HUP $MAINPID ExecStop=/bin/kill -s QUIT $MAINPID PrivateTmp=true [Install] WantedBy=multi-user.target
启动
[root@redis conf]# systemctl daemon-reload
[root@redis conf]# systemctl start redis6
6,每台机器:测试访问redis服务
[root@redis logs]# /usr/local/soft/redis-6.0.5/bin/redis-cli 127.0.0.1:6379> auth lhddemo OK 127.0.0.1:6379> set name lhd (error) CLUSTERDOWN Hash slot not served
提示cluster未启动
7,集群中任一台机器上:创建集群:
#-a: 输入登录验证密码
#--cluster create :用来创建集群,指定集群中机器的ip和端口
#--cluster-replicas :指定集群中的每个主节点的从节点的数量,1表示每个主节点各有一个从节点
[root@redis1 /]# /usr/local/soft/redis-6.0.5/bin/redis-cli -a lhddemo
--cluster create 172.17.0.2:6379 172.17.0.3:6379 172.17.0.4:6379 172.17.0.5:6379 172.17.0.6:6379 172.17.0.7:6379
--cluster-replicas 1
Can I set the above configuration? (type 'yes' to accept): yes
在这里输入yes 并回车
8, 集群中任一台机器上:查看创建集群的效果:查看集群信息:
#列出群集中的机器节点信息
[root@redis5 /]# /usr/local/soft/redis-6.0.5/bin/redis-cli -c -h 172.17.0.6 172.17.0.6:6379> auth lhddemo OK 172.17.0.6:6379> cluster nodes aa20aa58234477746468843269bc25b06bf1edd5 172.17.0.7:6379@16379 slave 8a66552f8869dc4c9ef81b473558cec6f55104dd 0 1593222901512 6 connected 6a8d2ccfed713a7d7023852686d24ef95520135d 172.17.0.4:6379@16379 master - 0 1593222898000 3 connected 10923-16383 a205c4ba5ba680381bfb8d349755a33c8c60f340 172.17.0.2:6379@16379 master - 0 1593222899496 1 connected 0-5460 52ca45c11d5d09207882ac9eb17bfccb81a6b713 172.17.0.6:6379@16379 myself,slave a205c4ba5ba680381bfb8d349755a33c8c60f340 0 1593222898000 5 connected 8a66552f8869dc4c9ef81b473558cec6f55104dd 172.17.0.3:6379@16379 master - 0 1593222900000 2 connected 5461-10922 dc271cb9bb59f163854ab16113e3d41234831ebe 172.17.0.5:6379@16379 slave 6a8d2ccfed713a7d7023852686d24ef95520135d 0 1593222900503 4 connected
四,配置文件说明:
1,application.properties:
spring.redis.cluster.nodes=172.17.0.2:6379,172.17.0.3:6379,172.17.0.4:6379,172.17.0.5:6379,172.17.0.6:6379,172.17.0.7:6379 spring.redis.password=lhddemo spring.session.store-type=redis #redis-lettuce spring.redis.lettuce.pool.max-active=8 spring.redis.lettuce.pool.max-wait=1 spring.redis.lettuce.pool.max-idle=8 spring.redis.lettuce.pool.min-idle=0
说明:
spring.redis.cluster.nodes:指定cluster中各redis节点
spring.redis.password: 登录密码
spring.session.store-type: 指定session的存储方式,这里使用redis
2,pom.xml
<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> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency>
五,java代码说明
1, DemoApplication.java
@SpringBootApplication @EnableRedisHttpSession(maxInactiveIntervalInSeconds = 60) public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }
说明:
EnableRedisHttpSession:启用redis作为session
maxInactiveIntervalInSeconds = 60指定session的时长,秒数,
建议时长3600秒
2,SessionController.java
@RestController @RequestMapping("/session") public class SessionController { /* * read session * */ @RequestMapping("/get") public Object getSession(HttpServletRequest request){ Map<String, Object> map = new HashMap<>(); map.put("sessionId", request.getSession().getId()); map.put("user", request.getSession().getAttribute("user")); map.put("maxInactiveInterval", request.getSession().getMaxInactiveInterval()); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String time = sdf.format(new Date(request.getSession().getCreationTime())); map.put("creationTime", time); return map; } /* * write session * */ @RequestMapping("/set/{name}") public String setSession(@PathVariable String name, HttpServletRequest request) { request.getSession().setAttribute("user", name); return "ok"; } }
六, 效果演示
1,设置session
2,读取session
3,从redis中查看session
172.17.0.4:6379> hgetall spring:session:sessions:e9f0e981-d3be-4f44-8783-7cbb3792bc23 1) "sessionAttr:user" 2) "xacxedx00x05tx00x0bgoodabcdefg" 3) "creationTime" 4) "xacxedx00x05srx00x0ejava.lang.Long;x8bxe4x90xccx8f#xdfx02x00x01Jx00x05valuexrx00x10java.lang.Numberx86xacx95x1dx0bx94xe0x8bx02x00x00xpx00x00x01rxf3x8d?+" 5) "maxInactiveInterval" 6) "xacxedx00x05srx00x11java.lang.Integerx12xe2xa0xa4xf7x81x878x02x00x01Ix00x05valuexrx00x10java.lang.Numberx86xacx95x1dx0bx94xe0x8bx02x00x00xpx00x00x00<" 7) "lastAccessedTime" 8) "xacxedx00x05srx00x0ejava.lang.Long;x8bxe4x90xccx8f#xdfx02x00x01Jx00x05valuexrx00x10java.lang.Numberx86xacx95x1dx0bx94xe0x8bx02x00x00xpx00x00x01rxf3x8d\x8a"
如果我们del这个session中,
session中记录的信息就会丢失
七,查看redis版本
[root@redis4 /]# /usr/local/soft/redis-6.0.5/bin/redis-server --version Redis server v=6.0.5 sha=00000000:0 malloc=jemalloc-5.1.0 bits=64 build=3432450123f459c8
八,查看spring boot版本
. ____ _ __ _ _ /\ / ___'_ __ _ _(_)_ __ __ _ ( ( )\___ | '_ | '_| | '_ / _` | \/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.3.1.RELEASE)