session 的持久化存储

session 的定义:

*参考koa-session源码

  • session 是一个概念,是一个数据对象,用来存储访问者的信息。
  • session 的存储方式由开发者自己定义,可存于内存,redis,mysql,甚至是 cookie 中。
  • 用户第一次访问的时候,我们就会给用户创建一个他的 session ,并在 cookie 中塞一个他的 “钥匙key” 。所以即使 http请求 是无状态的,但通过 cookie 我们就可以拿到访问者的 “钥匙key” ,便可以从所有访问者的 session 集合中取出对应访问者的 session。
  • 关闭浏览器,服务端的 session 是不会马上过期的。session 中间件自己实现了一套管理方式,当访问间隔超过 maxAge 的时候,session 便会失效。

session 的实现原理:

  • 1.第一次向服务器发送请求时在服务器端创建Session对象,该对象有一个唯一的ID

  • 2.在创建Session对象的同时会创建一个特殊的Cookie对象,该Cookie对象的名字是一个固定值JSESSIONID,该对象的值就是Session对象的ID值,同时会将这个特殊的Cookie对象发送给浏览器.

  • 3.以后浏览器在发送就会携带这个特殊的Cookie对象

  • 4.服务器获取JESSIONID的这个Cookie对象的value之后,在服务器中查找与之想对应的Session对象,来区分不同的用户

session对象的获取  :HttpSession session = request.getSession()

可以用如下的代码证明:

package xdp.gacl.session;

import java.io.IOException; import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import javax.servlet.http.HttpSession;

public class SessionDemo1 extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)
       throws ServletException, IOException {

    response.setCharacterEncoding("UTF=8");
    response.setContentType("text/html;charset=UTF-8");
    //使用request对象的getSession()获取session,如果session不存在则创建一个
    HttpSession session = request.getSession();
    //将数据存储到session中
    session.setAttribute("data", "是个麻瓜");
    //获取session的Id
    String sessionId = session.getId();
    //判断session是不是新创建的
    if (session.isNew()) {
        response.getWriter().print("session创建成功,session的id是:"+sessionId);
    }else {
        response.getWriter().print("服务器已经存在该session了,session的id是:"+sessionId);
    }
}

public void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    doGet(request, response);
}
复制代码

}

session 持久化存储的基本方法:

服务端:

  • 一个健壮的Web服务器会提供Session持久化的机制,在需要的时候(如服务器关闭的时候)将内存中的Session对象保存到持久存储设备中(如硬盘),这是通过对象序列化的技术来实现的:当需要重新加载Session对象时(如服务器再次启动的时候),通过对象反序列化的技术在内存中重新构造Session对象。
  • Tomcat通过Session Manager来创建和维护HTTP Session,当你没有配置其它的Session Manager实现时,默认使用StandardManager类。StandardManager在Tomcat服务器正常关闭、重启或者Web应用程序停止时,将内存中的所有活动的HttpSession对象序列化到硬盘文件中;当Web应用程序重新开始运行时,发序列化HttpSession对象,在内存中重新构建HttpSession对象,以及HttpSession中保存的所有对象(假定HttpSession对象没有过期)。
  • 除了StanardManager外,Tomcat还提供了SessionManager的持久化实现类org.apache.catalina.session.PersistentManager,该类需要经过元素的配置才能起作用,作为元素的子元素使用。使用PersistentManager,可以将HttpSession对象保存到文件中或者数据库表中。将HttpSession对象保存到数据库表中,就可以在集群环境中保持同一个会话。 koa2实现session的两种方式(基于Redis 和MySQL)
  • 1.基于MySQL的实现方式

这种方式需要安装koa-session-minimal和koa-mysql-session两个依赖。 执行

npm install koa-session-minimal koa-mysql-session --save 项目配置:

const session = require('koa-session-minimal');

const MysqlStore = require('koa-mysql-session');

const config = require('./config/default.js'); // 数据库配置

const Koa = require('koa');

const app = new Koa();

// session存储配置 const sessionMysqlConfig = { user: config.database.USERNAME, password: config.database.PASSWORD, database: config.database.DATABASE, host: config.database.HOST, };

// 配置session中间件 app.use(session({ key: 'USER_SID', store: new MysqlStore(sessionMysqlConfig) }));

这种方式会自动在数据库建立一个表 在浏览器的cookie中会生成一个以 USER_SID 为键的cookie。通过ctx的session属性可以修改更新删除session的值。 缺点是每次对session的操作需要查询数据库,比较耗时。

  • 2.基于Redis的实现方式

主要用到了koa-session2和ioredis。 执行

npm install koa-session2 ioredis --save 具体实现代码参考下面的项目实践与测试部分

每次登陆可以通过Redis来存储会话信息,由于Redis直接是运行在内存中的,因此速度会比较快。 通过get key 即可查看相应的session信息。

Redis:

Redis是一款开源的、高性能的键-值存储(key-value store)。它常被称作是一款数据结构服务器(data structure server)。

Redis集群~windows下搭建Sentinel环境及它对主从模式的实际意义:

使用ioredis存储session的具体步骤: 参考ioredis的接口文档,提供sentinel环境redis的存储

项目实践与测试:

在管理系统项目中实现redis对session的存储,其中,redis为哨兵模式集群

  • 安装相关插件库之后,首先定义用到的redis服务的sentinel端口

redis: {
//哨兵部署 sentinels: [ { host: '127.0.0.1', port: 26379 },

               { host: '127.0.0.1', port: 26380 },

               { host: '127.0.0.1', port: 26381 }
           ],
       //加这个才可以找到主服务器
       name:"mymaster",
  }
复制代码
  • 在index.js中按顺序添加:

const Store = require('./app/redis/redis-store');

app.use(session({

store:new Store(config.redis),

maxAge: 86400000 }))

//redis处理session持久化

app.use(require('./app/interceptors/redis-session'))

  • 由于引用了koa-session2,只需要将session置为undefined就会将session清空,添加./app/interceptors/redis-session.js

'use strict'; const config = require('config');

module.exports=async (ctx,next)=>{

ctx.destroySession=function () {

   var self = this;
   // console.log("destroySession")
   if(self.session){
       self.session=undefined;
       // console.log("shanchu")
       return true;
  }else{
       return false;
   }
复制代码

}; await next();

}

  • 取消登录引用定义的destroySession()方法

async function (ctx, next) { const self = this; try {

       // 如果已经登录,则直接返回
       if (ctx.hasLogin()) {

           ctx.destroySession();//删除session
           resp.success({ data: true }, ctx);
       } 

   } catch (e) {
       resp.failed({ desc: e.toString() }, ctx);
   } finally {
       // 执行流程交给下一个middle-ware
       await next();
   }
复制代码

}

运行项目之前按照上述sentinel环境的搭建指南搭建环境,并在项目中安装相关的库后运行项目

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值