《Shiro+Json Web Token》----用多线程优化登录
来源:互联网 发布:淘宝买家怎么修改评价 编辑:程序博客网 时间:2024/06/06 06:57
前言:
- 在最近这个权限框架中,小编发现登录很慢,因为是框架启动后第一次登录,需要创建很多对象还有打通额外的链接,所以很慢,但是第二次登录就明显的快了。于是打开项目的源码,开始优化起来,在了解完大体的业务逻辑后,感觉能用上多线程,于是就测试了一下,发现挺管用,小编将经验分享给大家吧!
使用的技术点
- SSM
- Shiro
- Json Web Token
- Redis
登录的逻辑
- 用户输入用户名和密码发送给后端程序,Shiro去验证
- 验证成功后,生成token信息,紧接着将token信息存入Redis
- 调用Dubbo服务,将用户的基础信息、存入Redis
- 调用Dubbo服务,将用户的权限标识存入Redis
给用户返回登录信息,主要是token信息
登录慢的原因
- Shiro在第一次认证的时候很耗时
第一次调用Dubbo服务的时候很耗时
在shiro第一次认证时,需要走shiro的内部很多程序,这耗点时间,第一调用dubbo服务,需要建立连接,也浪费点时间。
- 估计有读者在问,为什么还需要调用dubbo服务存入用户信息那?shiro认证完了用户信息不就在库里都搜出来了吗?原因是酱紫滴:因为用户的一些基本信息是其他服务提供的,不是权限框架提供的,这个权限框架是单独抽出来做认证、授权、单点登录用的,在自己的微服务中并不能将用户的所有信息都在自己的库中搜出来。
优化思路
- 当shiro认证通过之后,我们需要生成用户的token信息,将token信息存入实体后返回给前台,而在这个过程,调用dubb服务和往redis存入任何信息都是不耽误给前台返回信息的,也就是说登录逻辑中的第一步过后,第2、3、4不是互不干涉的,于是小编就将2、3、4步抽到子线程中去执行,结果效果非常明显。
- 让主线程去认证和返回用户信息,让子线程调用dubbo接口存入用户信息。
主要登录方法代码
@RestController@RequestMapping("/access")public class AccessController extends BaseController { @Autowired private UserService userService; //打印日志相关 private static final Logger logger = LoggerFactory.getLogger(AccessController.class); //创建一个线程池 ExecutorService cachedThreadPool = Executors.newCachedThreadPool(); @RequestMapping(value = "/login", method = RequestMethod.POST) public Object login(@RequestBody AllUsers allUsers) throws InterruptedException{ final CountDownLatch connectedSemaphore = new CountDownLatch(1); String userCode=allUsers.getUserCode(); String pwd=allUsers.getPassword(); final VOUserLogin userLogin = new VOUserLogin(); if(StringUtils.isEmpty(userCode)){ throw new UserCodeRequiredException(); } if(StringUtils.isEmpty(pwd)){ throw new PasswordRequiredException(); } //shiro进行登录验证 SecurityUtils.getSubject().login(new UsernamePasswordToken(userCode,pwd)); //验证成功后将用户信息搜出来 final AllUsers user= userService.findByUserCode(userCode); //生成token,返回userLogin对象 cachedThreadPool.execute(new Runnable() { public void run() { try { //上次访问的时间标志,将它和token一块存入redis中,解决token过期问题 String strNowMillis=String.valueOf(System.currentTimeMillis()); String lastLoninTime=PasswordUtil.base64Encoede(strNowMillis); //生成token String token=TokenUtil.generate(UUidUtil.generate(),user.getId(),"http://tfjybj.com",60*60*1000,user.getSchoolNo()); userLogin.setToken(token+"@"+lastLoninTime); BeanUtils.copyProperties(userLogin, user); connectedSemaphore.countDown();//释放信号,返回userLogin对象 String loginKey="aum"+":"+"tokenMessage"+":"+user.getSchoolNo()+":"+user.getId(); //向redis中存入登录信息(token) addMessageToRedis(loginKey,userLogin.getToken(),60*30); } catch (Exception e) { logger.error("AccessController.thread1 生成token并存入Redis失败:{}",e); } } }); cachedThreadPool.execute(new Runnable() { public void run() { String userInfoKey = "aum" + ":" + "userInfo" + ":" + user.getSchoolNo() + ":" + user.getId(); //向redis中 存入用户信息 UserModel userModel=new UserModel(); try { BeanUtils.copyProperties(userModel, user); addUserInfoToRedis(userInfoKey,userModel); //向redis中 存入用户权限标识信息 addPermissionsToRedis(userInfoKey,user.getSchoolNo()); } catch (Exception e) { logger.error("AccessController.thread2 向Redis存入用户信息和权限标识失败",e); } } }); //返回登录实体 connectedSemaphore.await(); return userLogin; }}
调用dubbo服务,向redis中存入用户信息
public void addUserInfoToRedis(String key,UserModel userModel){ userService.getUserInfo(key,userModel); }
调用dubbo服务,向redis中存入用户的权限标识
public void addPermissionsToRedis(String key,String schoolNo){ String userInfo= jedisCacheUtil.get(key); if (StringUtils.isNotBlank(userInfo)){ try { UserModel userModel=JacksonJsonUntil.jsonToPojo(userInfo, UserModel.class); List<String> roleIds=userModel.getRoleId(); if (roleIds.size()>0){ userService.getPermissionsFromRedis(roleIds,schoolNo); } } catch (IOException e) { e.printStackTrace(); } } }
小结
- 通过上面的优化,整个登录时间提升了大3/4,瞬间感觉到了多线程的魅力了,还有值得一提的是,小编由于用的是SpringMvc,登录所用的Handler是单例的,所以小编声明了一个带缓冲的线程池,也就是说,当有大量用户登录时,这个缓冲池就能提现效果了。
阅读全文
3 0
- 《Shiro+Json Web Token》----用多线程优化登录
- json web token登录
- json web token登录
- JSON Web Token (JWT) - 八幅漫画理解使用JSON Web Token设计单点登录系统
- 使用json web token
- 使用json web token
- JSON WEB TOKEN简介
- Json Web Token详解
- 使用json web token
- 使用json web token
- JWT -- json web token
- 使用json web token
- JSON WEB TOKEN 介绍
- JWT(JSON Web Token)
- JSON WEB TOKEN安全
- JSON Web Token
- JSON Web Token (JWT)
- Json Web Token
- C语言——行列倒置函数实现
- 运行Java程序的参数
- 模式识别算法中英文对照
- 暑期集训之会场安排问题
- centos安装xampp更换端口以及数据库远程访问
- 《Shiro+Json Web Token》----用多线程优化登录
- 自我介绍
- 51nod 1065 最小正子段和(前缀和+思维) && 1051最大子矩阵和(枚举+最大子段和)
- HTTP
- 汇编语言:基础知识(第一章)——学习笔记
- PAT 1070结绳
- TensorFlow笔记之简单cnn
- nginx 502问题
- 堆