知識點(diǎn) : session + 持久化

前面是瞎扯,代碼在后面。

前言

http 請求是無狀態(tài)的,什么是無狀態(tài)呢,就是你先后向服務(wù)器發(fā)送兩個(gè)請求,服務(wù)器那邊比較糊涂,自己是沒有辦法識別這兩個(gè)請求是否是同一個(gè)用戶發(fā)送來的。

也就是說,我上一秒給你五毛錢你下一秒就不認(rèn)賬的意思。

為了避免這種情況發(fā)生,我們告訴服務(wù)器,對岸的朋友來的時(shí)候,你給他一個(gè)簽名,告訴他,下次帶著簽名過來,確認(rèn)一下是不是對的人。

當(dāng)然,這個(gè)簽名也是有 有效期 的。

所以,我們開發(fā)者就在用戶第一個(gè)請求過來的時(shí)候存起來,然后給用戶一個(gè)對應(yīng)的標(biāo)識,這個(gè)標(biāo)識也是有 有效期 的,用戶下一個(gè)請求過來的時(shí)候判斷一下這個(gè)標(biāo)識是否對應(yīng)是否符合條件,if true next else redirect ,就這樣。

當(dāng)然,程序員是無敵的嘛,我們有一百種改變世界的辦法,如今,我已經(jīng)找到了這樣的辦法,本篇簡書就到此結(jié)束,謝謝大家?。?!

調(diào)皮

session

What!??!看到這里你還問我 session 是什么?WTF

嘿siri,session 是什么東東

Session:在計(jì)算機(jī)中,尤其是在網(wǎng)絡(luò)應(yīng)用中,稱為“會話控制”。Session 對象存儲特定用戶會話所需的屬性及配置信息。這樣,當(dāng)用戶在應(yīng)用程序的 Web 頁之間跳轉(zhuǎn)時(shí),存儲在 Session 對象中的變量將不會丟失,而是在整個(gè)用戶會話中一直存在下去。當(dāng)用戶請求來自應(yīng)用程序的 Web 頁時(shí),如果該用戶還沒有會話,則 Web 服務(wù)器將自動創(chuàng)建一個(gè) Session 對象。當(dāng)會話過期或被放棄后,服務(wù)器將終止該會話。Session 對象最常見的一個(gè)用法就是存儲用戶的首選項(xiàng)。例如,如果用戶指明不喜歡查看圖形,就可以將該信息存儲在 Session 對象中。有關(guān)使用 Session 對象的詳細(xì)信息,請參閱“ASP 應(yīng)用程序”部分的“管理會話”。注意 會話狀態(tài)僅在支持 cookie 的瀏覽器中保留。

嘿siri,自殺

......

簡單的說,session 可以用來維持會話,服務(wù)器每天要接受 XXX 個(gè)請求,上面說了 http 是無狀態(tài)的,哪能分得出誰是誰,不過 session 可以用來幫助服務(wù)器區(qū)分哪些請求對應(yīng)哪些用戶,對的,就這樣,不知道有沒有說清楚~

舉個(gè)例子吧,剛學(xué)編程時(shí)會接觸到登陸功能,登錄成功的時(shí)候一定要存一個(gè) session 然后返回到用戶的 cookie 中,用來保持這個(gè)用戶的會話信息,用戶下個(gè)請求攜帶著 cookie 信息來的時(shí)候判斷一下該用戶是否登錄,然后在進(jìn)行后續(xù)的一頓操作,嗯,就這樣 ~ 還有不懂得可以在網(wǎng)上找一些資料更詳細(xì)的了解一下這一塊 ~

基于內(nèi)存來管理 session

剛開始我們?yōu)榱朔奖憧旖輹?session 存在服務(wù)器的內(nèi)存中,就像下面這樣:

變動的地方會用 start 和 end 標(biāo)識出來

// app.js 文件中
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
// start 
// 安裝 express-session 模塊 并引入
var session = require('express-session'); 
// end
var logger = require('morgan');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());

// start 
// session 的一些配置
app.use(session({
  secret: 'zz',
  cookie:{maxAge:60000},
  resave: false,
  saveUninitialized: true
}));
// end

app.use('/static',express.static(path.join(__dirname, 'public')));

app.use('/', indexRouter);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  next(createError(404));
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

// ./routes/index.js 文件中
var express = require('express');
var router = express.Router();

/* GET home page. */
// 用來為這個(gè)用戶存儲一個(gè) session
router.get('/a', function(req, res, next) {
  var a = Math.floor(Math.random()*10)+''
  req.session.user = a
  res.send(a)
});

// 在頁面上打印自己在 session 中存儲的信息
router.get('/b', function(req, res, next) {
  req.session.touch();
  res.send(req.session.user)
});

module.exports = router;

http://localhost:3000/a
http://localhost:3000/b

上面這種基于內(nèi)存來存儲 session 方法唯一的好處是方便省事,適合初學(xué),但是也存在好多缺點(diǎn)。比如說:

  1. 如果用戶量比較大,session 會把內(nèi)存占滿
  2. 服務(wù)器掛了,然后重啟后 session 就不存在了
  3. 項(xiàng)目部署在多臺服務(wù)器的集群中,就不好使了
    ......

基于 mongo 來管理 session

不一定要用 mongo 來管理 session,你們可以用 redis 、 memcache 、mysql 等都可以,我這里用 mongo 是因?yàn)殡娔X里面剛裝了個(gè) mongo , 就順手拿來用了。

話不多說,先上代碼為敬~

// app.js 文件中, ./routes/index.js 文件不變
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
// start 
// 引入 這兩個(gè) 第三方庫
var session = require('express-session');
var MongoStore = require('connect-mongo')(session);
// end
var logger = require('morgan');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());

// start
// 設(shè)置 session 存儲的一些配置選項(xiàng)
app.use(session({
  secret: 'zz',
  cookie: {
      maxAge: 10000
  },
  resave: false,
  saveUninitialized: true,
  store: new MongoStore({
    url:'mongodb://localhost/ims',
    collection:'sessions'
  })
}))
// end

app.use('/static',express.static(path.join(__dirname, 'public')));

app.use('/', indexRouter);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  next(createError(404));
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

http://localhost:3000/a
http://localhost:3000/b
mongo 中 session 數(shù)據(jù)

上圖中可以看到,mongo 中存儲了一條 session 記錄,這樣你如果項(xiàng)目跑在多臺服務(wù)器的話,這條 session 記錄就可以在這多臺服務(wù)器中共享,即使其中某臺服務(wù)器掛了也不影響 session 的存儲,從而來達(dá)到 session 持久化存儲。

總結(jié)

基于內(nèi)存的 session 存儲

0.如果用戶量比較大,session 會把內(nèi)存占滿

1.服務(wù)器掛了,然后重啟后 session 就不存在了

2.項(xiàng)目部署在多臺服務(wù)器的集群中,就不好使了

......

session 持久化存儲

0.提高服務(wù)器內(nèi)存的利用率

1.在多臺服務(wù)器同時(shí)對外提供服務(wù)的集群系統(tǒng)中,可以共享 session

2.當(dāng)某臺服務(wù)器掛掉后,重啟以后還可以使用之前未過期的 session

這么枯燥乏味的文章能看到這里已經(jīng)很棒了,這些東西都太抽象了,剛開始肯定不好理解,建議多查詢一些資料,親自試驗(yàn)一下,感受一下成功的喜悅,嗯哼~

??
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 關(guān)于Mongodb的全面總結(jié) MongoDB的內(nèi)部構(gòu)造《MongoDB The Definitive Guide》...
    中v中閱讀 32,329評論 2 89
  • 從三月份找實(shí)習(xí)到現(xiàn)在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,901評論 11 349
  • Java繼承關(guān)系初始化順序 父類的靜態(tài)變量-->父類的靜態(tài)代碼塊-->子類的靜態(tài)變量-->子類的靜態(tài)代碼快-->父...
    第六象限閱讀 2,261評論 0 9
  • 目錄Cookie機(jī)制什么是CookieCookie的不可跨域名性Unicode編碼:保存中文BASE64編碼:保存...
    Tomatoro閱讀 17,065評論 7 186
  • 1、簡述 網(wǎng)絡(luò)的七層協(xié)議從上到下:7、應(yīng)用層 6、表示層 5、會話層 4、傳輸層 3、網(wǎng)絡(luò)層 2、數(shù)據(jù)鏈路層 1...
    starHanJu閱讀 414評論 0 2

友情鏈接更多精彩內(nèi)容