koa框架21 扩展session mysql
session 的一些问题
- 无法共享,因为所有网站不可能共用一台服务器,可能会有多个
- 不安全,如果服务器崩溃,数据也会丢失
- 性能低,普通的session文件都是存放本地,io非常慢(相对)
于是就有两中方式进行优化:
- 丢数据库mysql
- 丢redis中
mysql
koa作者提供了一个接口store,这个接口也是在session的配置对象里的,他是一个对象,里面有三个生命周期函数,我称之为生命周期函数。
他们会在session操作完后触发。
server.use(session({
maxAge: 20 * 60 * 1000,
renew: true,
store: {
get(key, maxAge) { //获取
},
set(key, session, maxAge) { //设置
},
destroy(key) { //删除
}
}
}, server));
get是获取,session要从mysql获取的话,通过这个函数返回给koa数据。所有需要一个key,一个过期时间做判断
set是设置,设置的话,key是必须的,然后就是session对象本身的值了,还有就是过期时间
destroy是删除,删除的话有key就行了。
数据库创建
我们需要创建一个数据库session,数据库里面要有一个表,用于存储session信息的,命名为user_session
表里面有几个字段:
- ID 唯一,主键,int类型(int只有11位),不能为null,自增
- sessID,唯一,主键,varchar类型(80长度),不能为null,存放key
- view int类型,这个是我们自制的属性,用于存放浏览次数
- expires int类型,用于存放过期时间,必须为秒,因为int只有11位
四个字段创建好后,我们就可以连接这个数据了
const mysql = require("promise-mysql");
(async () => {
const sessionDB = await mysql.createPool({
host: "localhost",
user: "root",
pass: "123456",
database: "session"
});
})();
由于使用了promise-mysql,他的方法是一个异步的,所以做一个自运行函数,async开头
然后我们就可以先写get方法:
async get(key, maxAge) { //获取
const data = await sessionDB.query("SELECT* FROM user_session WHERE sessID=?", [key]);
if (data.length) { //存在
if (data.expires * 1000 < Date.now() + maxAge) { //过期
return {};
} else { //没过期
return {
view: data[0]["view"]
};
}
} else { //不存在
return {};
}
},
get是获取,从mysql里面拿数据,于是使用了SELETE 搜索所有user_session表里面,sessID要等于key的数据。
他会返回一个数组,所有的数据库操作都会返回一个数组,我们判断这个数组的length,判断是否有值。
没有就表示这是一个新用户,我们返回一个空对象,有的话,就判断时间有没有过期。
mysql里面存储的时间必须是秒,而且必须是正确的年月日那种秒,你不可能存个20秒,谁知道你这个20秒是哪段时间的,所以数据库的时间必须是当前时间+过期时间
所以我们乘以1000转换成秒,然后判断和当前时间的大小,如果小于,那就过期了,那就返回一个空对象。
如果没有过期,那就返回一个session里面存储的数据对象,像id,哪些肯定是不返回的,因为我们自制的只有一个view。
set方法:
async set(key, session, maxAge) { //设置
const isKey = await sessionDB.query("SELECT* FROM user_session WHERE sessID=?", [key]);
const expires = Math.floor((Date.now() + maxAge) / 1000);
if (isKey.length) { //已存在,进行更新数据
await sessionDB.query("UPDATE user_session SET view=?,expires=? WHERE sessID=?", [session.view, expires, key]);
} else { //不存在,直接添加
await sessionDB.query("INSERT INTO user_session (sessID,view,expores) VALUES(?,?,?)", [key, session.view, expires]);
}
},
设置的话需要判断下有没有存在这个key,如果存在是更新,不存在是直接添加。
由于数据库的时间是秒,所我们用当前时间+过期时间,除以1000转成秒,然后去除浮点数,得到存入数据的时间。
然后就是设置数据库的内容了。
删除
async destroy(key) { //删除
await sessionDB.query("DELETE FROM user_session WHERE sessID=?", [key]);
}
定时清理session
session是一个和浏览器建立连接后的一个临时存储,如果用户超时未连接的话,session就会失效了。
但是由于我们使用的是mysql存储,所有实际上弃用的session还存储在我们的mysql里面,我们需要及时清理掉
//定时清理 10分钟
setInterval(async () => {
await sessionDB.query("DELETE FROM user_session WHERE expires<?", [Math.floor(Date.now() / 1000)])
}, 10 * 60 * 1000)
创建一个无限定时器吗,十分钟运行一次,然后判断表里面时间小于当前时间的,直接删除。
本文系作者 @木灵鱼儿 原创发布在木灵鱼儿站点。未经许可,禁止转载。
暂无评论数据