这里的session,指的是node服务的session,为了服务的稳定性,运维方面是用nginx来做负载均衡,需要部署多个实例,那么问题就出现了,该如何共享session呢?
首先,关于session这一块的处理,依赖的是express-session这个中间件,它原本是包含在express中的,后来express版本升级之后,将这些模块都拆分成对应的中间件。
当然,我们肯定还是使用这个模块,毕竟已经比较成型。
下面简单看一下关于它的配置:1
2
3
4
5
6
7
8app.use(session({
secret:config.session_secret,
resave:false,
saveUninitialized:false,
cookie:{
maxAge:1000*60*60*24
}
}));
这个是我代码中的一个简单配置,具体的例子可以在google上搜索一下。
默认的一些参数,在文档上可以看到,因为我们这里是主要解决共享问题,跟这个相关的,主要是里面store的配置信息。
默认情况下,session是保存在内存中,这样可能不太稳定,并且对于多实例部署,它不能够共享。
既然要共享,就肯定需要一个保存的地方,并且多个实例之间都可以进行读取。你肯定想到了数据库,nice!
做法肯定是这样的,如果是是用mysql或者mogondb之类的,从效率上,可能会略低一点,并且,我们本意的前后端分离,前端是不直接连接数据库的,
但是,现在需求上的改动需要我们这样来做,还有一个首选,缓存数据库!
如果你对服务端有一定了解的话,你就肯定想到的是redis。所以这一点,我也是选择了redis(ps:因为我们后端本身就是用的redis,如果遇到不懂的地方还可以向后端同学请教)
其实当前的业务需求只是为了保持登录,存储用户的一些简单信息,在这里,我们依赖中间件本身,可以让我们节省很多事情。
具体操作如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15const client = redis.createClient({
port: config.redisOptions.port,
host: config.redisOptions.host,
});
app.use(session({
store: new RedisStore({
client: client
}),
secret:config.session_secret,
resave:false,
saveUninitialized:false,
cookie:{
maxAge:1000*60*60*24
}
}));
就是在这里面来指定一下store的存放位置。
client参数是一个redis连接的实例。是不是觉得就是这样简单的呢?当然是,我们的操作都是通过
req.session.*来进行完成,从这个层面来考虑的话,我们基本上还是不进行数据库的操作。1
2
3
4
5req.session.username = '11111';
let username = req.session.username;
还有一点,在开发环境,session存入内存是没有问题的,但是在生产环境,如果你制定了NODE_ENV=production,它会给一个警告。
基于此做法,我们的session就是放入redis了,在多个实例的情况,我们也解决了session共享的问题。
当然你也可以通过client来进行一些数据的存储,放入redis,但是我还是不建议这样做,因为我们现在的讨论的毕竟还是前后端分离,
如果你是应用在基于nodejs全栈开发的话,这样做当然没有任何问题~
以上是个人的一些理解,如果有不对的地方,还望各路大牛进行指导