📒博客首页:崇尚学技术的科班人
🍣今天给大家带来的文章是《分布式系统下的session怎样存储》
🍣
🍣希望各位小伙伴们能够耐心的读完这篇文章🍣
🙏博主也在学习阶段,如若发现问题,请告知,非常感谢🙏
💗同时也非常感谢各位小伙伴们的支持💗
(1)、定义
这里我引用名人Leslie Lamport
一句话
多个自治的处理元素
,不共享主内存
,但 通过网络发送消息合作
。(2)、三个特点和三个概念
三个特点
三个概念
(3)、分布式和集群的区别和联系
All In One
的项目,它上面部署了很多的集群节点,但是它就不是分布式系统。用户登录
就是验证身份和存储信息,用户登出
就是将浏览状态失效。http
协议是无状态的,对于同一次http
请求是没有上下文关系的。session(会话控制)
来存储用户信息和用户浏览状态。JSESSIONID
的key
和value
。服务器通过setCookie
将JSESSIONID
设置在http
请求头上,客户端会将该信息存储在客户端内部,然后每一次请求都会带上该信息。token
方式的话,我们需要手动的在http
请求头上或者url
上设置token
字段,请求发送到服务器的时候,服务器回去出token
字段的相关值进行验证。如果要求十分严格的话,token
会结合签名一起使用。1. 非分布式系统下的架构情况
2. 分布式系统下的架构情况
tomcat
服务器上,这样多个服务器上的部署内容是不相同的。session
该如何进行存储?**解决该问题的最好的方法:**就是利用redis
做缓存,然后多台tomcat
从redis
进行查询,进而获得对应用户的信息,进而进行后续操作。这样就能很好的解决分布式系统下的session
问题。
ReidsConstant
/**
* redis常量
* @author :小肖
* @date :Created in 2022/2/7 21:41
*/
public interface RedisConstant {
String TOKEN_PREFIX = "token_%s";
Integer EXPIRE = 7200; // 设置过期时间,单位是s
}
CookieConstant
/**
* @author :小肖
* @date :Created in 2022/2/7 21:55
*/
public interface CookieConstant {
String TOKEN = "token";
Integer expire = 7200; // 单位是秒
}
CookieUtil
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
/**
* @author :小肖
* @date :Created in 2022/2/7 21:47
*/
public class CookieUtil {
public static void set(HttpServletResponse response,
String name,
String value,
int maxAge){
Cookie cookie = new Cookie(name,value);
cookie.setPath("/");
cookie.setMaxAge(maxAge);
response.addCookie(cookie);
}
public static Cookie get(HttpServletRequest request,
String name){
Map<String, Cookie> cookieMap = getCookieMap(request);
if(cookieMap.containsKey(name)){
return cookieMap.get(name);
}else{
return null;
}
}
private static Map<String,Cookie> getCookieMap(HttpServletRequest request){
Map<String,Cookie> map = new HashMap<>();
Cookie[] cookies = request.getCookies();
if(cookies != null){
for(Cookie cookie : cookies){
map.put(cookie.getName(),cookie);
}
}
return map;
}
}
ProjectUrl
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @author :小肖
* @date :Created in 2022/2/7 15:19
*/
@ConfigurationProperties("projectUrl")
@Data
@Component
public class ProjectUrl {
/**
* 微信公众平台授权url
*/
public String wechatMpAuthorize;
/**
* 微信开放平台授权url
*/
public String wechatOpenAuthorize;
/**
* 项目地址
*/
public String sell;
}
SellerUserController
import com.xiao.bean.SellerInfo;
import com.xiao.config.ProjectUrl;
import com.xiao.constant.CookieConstant;
import com.xiao.constant.RedisConstant;
import com.xiao.enums.ResultEnum;
import com.xiao.service.SellerService;
import com.xiao.utils.CookieUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
/**
* 卖家用户信息
* @author :小肖
* @date :Created in 2022/2/7 21:26
*/
@Controller
@RequestMapping("/seller")
public class SellerUserController {
@Autowired
private SellerService sellerService;
@Autowired
private StringRedisTemplate redisTemplate;
@Autowired
private ProjectUrl projectUrl;
/**
* 该url可以和微信登录的扫码登录进行配置,可以作为returnUrl进行配置
* 登录
* @param openid
* @param response
* @param map
* @return
*/
@GetMapping("/login")
public ModelAndView login(@RequestParam("openid") String openid,
HttpServletResponse response,
Map<String, Object> map) {
// 1. 查询数据库匹对信息
SellerInfo sellerInfo = sellerService.findSellerInfoByOpenid(openid);
if(sellerInfo == null){
map.put("msg", ResultEnum.LOGIN_FAIL.getMessage());
map.put("url","/sell/seller/order/list");
return new ModelAndView("common/error", map);
}
// 2. 向redis 中设置token
String token = UUID.randomUUID().toString();
Integer expire = RedisConstant.EXPIRE;
redisTemplate.opsForValue().set(String.format(RedisConstant.TOKEN_PREFIX,token),openid,expire, TimeUnit.SECONDS);
// 3. 添加cookie
CookieUtil.set(response, CookieConstant.TOKEN,token,expire);
return new ModelAndView("redirect:" + projectUrl.getSell() + "/sell/seller/order/list");
}
/**
* 登出
* @param request
* @param response
* @param map
* @return
*/
@GetMapping("/logout")
public ModelAndView logout(HttpServletRequest request,
HttpServletResponse response,
Map<String, Object> map) {
Cookie cookie = CookieUtil.get(request, CookieConstant.TOKEN);
if(cookie != null){
// 1. 清除redis
redisTemplate.opsForValue().getOperations().delete(String.format(RedisConstant.TOKEN_PREFIX,cookie.getValue()));
// 2. 清除cookie
CookieUtil.set(response,CookieConstant.TOKEN,null,0);
}
map.put("msg",ResultEnum.LOGOUT_SUCCESS.getMessage());
map.put("url","/sell/seller/order/list");
return new ModelAndView("common/success",map);
}
}
redis
缓存中,并设置相关的过期时间,如果用户登出的时候我们就将其在redis
缓存中删除。版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/weixin_56727438/article/details/122807249
内容来源于网络,如有侵权,请联系作者删除!