session 的持久化存儲

session 的定義:

*參考koa-session源碼html

  • session 是一個概念,是一個數據對象,用來存儲訪問者的信息。
  • session 的存儲方式由開發者本身定義,可存於內存,redis,mysql,甚至是 cookie 中。
  • 用戶第一次訪問的時候,咱們就會給用戶建立一個他的 session ,並在 cookie 中塞一個他的 「鑰匙key」 。因此即便 http請求 是無狀態的,但經過 cookie 咱們就能夠拿到訪問者的 「鑰匙key」 ,即可以從全部訪問者的 session 集合中取出對應訪問者的 session。
  • 關閉瀏覽器,服務端的 session 是不會立刻過時的。session 中間件本身實現了一套管理方式,當訪問間隔超過 maxAge 的時候,session 便會失效。

session 的實現原理:

  • 1.第一次向服務器發送請求時在服務器端建立Session對象,該對象有一個惟一的IDjava

  • 2.在建立Session對象的同時會建立一個特殊的Cookie對象,該Cookie對象的名字是一個固定值JSESSIONID,該對象的值就是Session對象的ID值,同時會將這個特殊的Cookie對象發送給瀏覽器.mysql

  • 3.之後瀏覽器在發送就會攜帶這個特殊的Cookie對象git

  • 4.服務器獲取JESSIONID的這個Cookie對象的value以後,在服務器中查找與之想對應的Session對象,來區分不一樣的用戶github

session對象的獲取  :HttpSession session = request.getSession()redis

能夠用以下的代碼證實:sql

package xdp.gacl.session;數據庫

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

import javax.servlet.http.HttpServlet;npm

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環境的搭建指南搭建環境,並在項目中安裝相關的庫後運行項目

相關文章
相關標籤/搜索