上一篇: 微服务(十)—— Feign的使用.
1. 介绍
在单服务下,用户通过浏览器登录,通过会话管理保存用户登录信息,Cookie通过在客户端记录信息确定用户身份,Session通过在服务端记录信息确定用户身份。
当浏览器访问服务器时,会创建一个Session对象,同时Session对象里会随机生成一个id值,然后通过response返回给浏览器保存在cookie里,当浏览器下一次访问服务器时,会根据浏览器所带的cookie里的id找到对应的session。
但是对于微服务来说,session保存在不同的服务器,所以用户登录后访问不同的服务就需要重新登录,者显然是不合理的。
这就需要解决session问题,有下面几种实现方式:
(1)session同步
Tomcat支持动态的将某个Tomcat下的session复制到其它的Tomcat中。
这种方式在集群数量比较少的时候,使用还可以。如果集群数量庞大,都需要复制session,这时候会因为网络延迟,或者session比较大,同步慢等问题。
(2)session黏着(放在服务端)
通过对IP地址或者域名地址进行hash;解决了第一个网络延迟同步慢的问题。
缺点: 用户浏览器的IP地址hash后,满足单调性。可能会造成资源分配的不均衡,就不能达到负载均衡的目的。
(3)将信息存放到cookie客户端
session存在服务器端,会对服务器端有一定的压力,如果将信息保存到cookie中,不但减轻了服务器的压力,同时每个客户端的压力也很小。
缺点: cookie可以被禁用,cookie要随着浏览器传递,增大了传送的内容,而且cookie大小也有限制。
(4) SSO单点登录
将session从系统中独立出来。建立一个专门的服务去保存session 信息,其它服务需要session信息的时候都去请求这个服务。一般都是保存在Redis中,因为Redis的访问速度快。
2. 实现过程
我在系统中使用的是第四种方式——SSO单点登录。
2.1 思路
首先用户登录,登录成功后将用户信息存储在Redis数据库中,并且将键的过期时间设置为 1 小时。我这里是用用户名为键,用户对象信息为值,我将用户对象转换为json格式存储在数据库中。因为我在建立用户表的时候,将用户名加了唯一索引 并且注册的时候做了唯一判断,所以不存在键冲突的情况。
然后告诉前端,每次向后端发送请求的时候将用户名放到请求头中,后端在需要用户登录的接口先从请求头中获取用户名,然后从Redis中根据键取出值,如果值为空,说明用户没有登录,返回一个需要登录的信息;如果不为空,说明已经成功登录,就不需要再登录。并且将该信息再次存在Redis,并且将过期时间设置为 1 小时。
这样不仅解决了单点登录的问题,还解决了登录过期重新登录的问题。
2.2 实现
首先,写一个Redis的配置类:RedisConfig
package com.aiun.common.config;
/**
* Redis配置类
* @author lenovo
*/
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String,Object> redisTemplate(LettuceConnectionFactory redisConnectionFactory){
RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
//为string类型key设置序列器
redisTemplate.setKeySerializer(new StringRedisSerializer());
//为string类型value设置序列器
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
//为hash类型key设置序列器
redisTemplate.setHashKeySerializer(new StringRedisSerializer())