除非在客户端上设置了某些事件来通知服务器窗口正在关闭,否则服务器将无法知道会话不再使用。
您需要将会话精神上视为两部分。一部分是令牌(cookie),它在节点和浏览器之间传递。第二部分是将会话实际持久化存储在存储中(基本的MemoryStore或Redis,或者另一个数据库的新会话存储)。所有的连接会话代码所做的就是将其与每个请求进行匹配。
检查会话cookie。
如果存在,则尝试在存储中查找它。
使从存储检索到的数据对请求可用。
在请求结束时,更新cookie的TTL信息。
将会话写回存储。
请注意,除非使用MemoryStore,否则Node在处理请求时以外的时间内并不在内存中存储会话数据。(嗯,它会在内存中存储一段时间,但会被取消引用并且可能会被垃圾回收)。当您考虑各种部署方案时,这很有意义。
因此,服务器端会话过期的工作落在存储本身上。Redis之所以很棒,其中之一原因是因为它可以自动管理过期的内容,您可以在其set操作中看到connect-redis在
执行此操作。
RedisStore.prototype.set = function(sid, sess, fn){
sid = this.prefix + sid;
try {
var maxAge = sess.cookie.maxAge
, ttl = this.ttl
, sess = JSON.stringify(sess);
ttl = ttl || ('number' == typeof maxAge
? maxAge / 1000 | 0
: oneDay);
debug('SETEX "%s" ttl:%s %s', sid, ttl, sess);
this.client.setex(sid, ttl, sess, function(err){
err || debug('SETEX complete');
fn && fn.apply(this, arguments);
});
} catch (err) {
fn && fn(err);
}
};
您可以看到,它将TTL除以1000,因为它使用秒而不是毫秒来设置过期时间。最受欢迎的MongoDB会话存储
也是这样使用 MongoDB的TTL功能。
所以,长话短说,您要么依靠您的数据库引擎自动提供服务器端会话过期,要么需要自己实现过期。您可以在节点应用程序之外拥有一个进程(可能是另一个节点进程)来执行此操作,或者您的存储实现可以安装SetInterval任务以定期检查和清理它。例如,基于MySQL的会话存储
就是这样做的
关于您问题的第二部分,什么是
length
和
clear
?评论者正确指出RedisStore没有实现这些功能,但是您可以在
MemoryStore源代码中看到它们的实现。不太令人兴奋。
clear
清空所有会话,并在提供回调时调用回调:
MemoryStore.prototype.clear = function(fn){
this.sessions = {};
fn && fn();
};
length
方法只是简单地返回存储中会话的数量:
MemoryStore.prototype.length = function(fn){
fn(null, Object.keys(this.sessions).length);
};
希望这对您有所帮助。