自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

快醒醒,Cookie + Session 的時(shí)代已經(jīng)過(guò)去了

開(kāi)發(fā) 前端
由于 HTTP 協(xié)議是無(wú)狀態(tài)的,完成操作關(guān)閉瀏覽器后,客戶端和服務(wù)端的連接就斷開(kāi)了,所以我們必須要有一種機(jī)制來(lái)保證客戶端和服務(wù)端之間會(huì)話的連續(xù)性,常見(jiàn)的,就是使用 Cookie + Session(會(huì)話) 的方式。

[[425987]]

本文轉(zhuǎn)載自微信公眾號(hào)「飛天小牛肉」,作者小牛肉 。轉(zhuǎn)載本文請(qǐng)聯(lián)系飛天小牛肉公眾號(hào)。

這篇文章主要在做 Echo 社區(qū)項(xiàng)目的時(shí)候?qū)懙模诒3钟脩舻卿洃B(tài)的這個(gè)需求下,為啥要用 ThreadLocal 存儲(chǔ)用戶信息,而不是采用常見(jiàn)的 Cookie + Session。

Cookie + Session

由于 HTTP 協(xié)議是無(wú)狀態(tài)的,完成操作關(guān)閉瀏覽器后,客戶端和服務(wù)端的連接就斷開(kāi)了,所以我們必須要有一種機(jī)制來(lái)保證客戶端和服務(wù)端之間會(huì)話的連續(xù)性,常見(jiàn)的,就是使用 Cookie + Session(會(huì)話) 的方式。

具體來(lái)說(shuō),當(dāng)客戶端請(qǐng)求服務(wù)端的時(shí)候,服務(wù)端會(huì)為此次請(qǐng)求開(kāi)辟一塊內(nèi)存空間(Session 對(duì)象),服務(wù)端可以在此存儲(chǔ)客戶端在該會(huì)話期間的一些操作記錄(比如用戶信息就可以存在 Session 中),同時(shí)會(huì)生成一個(gè) sessionID ,并通過(guò)響應(yīng)頭的 Set-Cookie:JSESSIONID=XXXXXXX 命令,將 seesionID 存儲(chǔ)進(jìn)客戶端的 Cookie 中。

可能會(huì)有同學(xué)問(wèn)為啥不直接把數(shù)據(jù)全部存在 Cookie 中,還整個(gè) Session 出來(lái)然后把 sessionID 存在 Cookie 中的?

Cookie 長(zhǎng)度的限制:首先,最基本的,Cookie 是有長(zhǎng)度限制的,這限制了它能存儲(chǔ)的數(shù)據(jù)的長(zhǎng)度

性能影響:Cookie 確實(shí)和 Session 一樣可以讓服務(wù)端程序跟蹤每個(gè)客戶端的訪問(wèn),但是每次客戶端的訪問(wèn)都必須傳回這些 Cookie,那如果 Cookie 中存儲(chǔ)的數(shù)據(jù)比較多的話,這無(wú)疑增加了客戶端與服務(wù)端之間的數(shù)據(jù)傳輸量,增加了服務(wù)器的壓力。

安全性:Session 數(shù)據(jù)其實(shí)是屬于服務(wù)端的數(shù)據(jù),而 Cookie 屬于客戶端,把本應(yīng)在 Session 中存儲(chǔ)的數(shù)據(jù)放到客戶端 Cookie,使得服務(wù)端數(shù)據(jù)延伸到了外部網(wǎng)絡(luò)及客戶端,顯然是存在安全性上的問(wèn)題的。當(dāng)然我們可以對(duì)這些數(shù)據(jù)做加密,不過(guò)從技術(shù)來(lái)講物理上不接觸才是最安全的。

這樣,按照 Cookie + Seesion 的機(jī)制,服務(wù)端在接到客戶端請(qǐng)求的時(shí)候,只要去 Cookie 中獲取到 sessionID 就能據(jù)此拿到 Session 了。Session 存活期間,我們認(rèn)為客戶端一直處于活躍狀態(tài)(用戶處于登錄態(tài)),一旦 Session 超期過(guò)時(shí),那么就可以認(rèn)為客戶端已經(jīng)停止和服務(wù)器進(jìn)行交互了(用戶退出登錄)。

如果遇到禁用 Cookie 的情況,一般的做法就是把這個(gè) sessionID 放到 URL 參數(shù)中。這也是經(jīng)常在面試中會(huì)被問(wèn)到的問(wèn)題。

這種機(jī)制在單體應(yīng)用時(shí)代應(yīng)用非常廣泛,但是,隨著分布式時(shí)代的到來(lái),Session 的缺點(diǎn)也逐漸暴露出來(lái)。

舉個(gè)例子,比如我們有多個(gè)服務(wù)器,客戶端 1 向服務(wù)器發(fā)送了一個(gè)請(qǐng)求,由于負(fù)載均衡的存在,該請(qǐng)求被轉(zhuǎn)發(fā)給了服務(wù)器 A,于是服務(wù)器 A 創(chuàng)建并存儲(chǔ)了這個(gè) Session

緊接著,客戶端 1 又向服務(wù)器發(fā)送了一個(gè)請(qǐng)求,但是這一次請(qǐng)求被負(fù)載均衡給了服務(wù)器 B,而服務(wù)器 B 這時(shí)候是沒(méi)有存儲(chǔ)服務(wù)器 A 的 Session 的,這就導(dǎo)致 Session 的失效。

明明用戶在上一個(gè)界面還是登錄的,跳到下一個(gè)界面就退出登錄了,這顯然不合理。

分布式集群 Session 共享

當(dāng)然了,對(duì)此的解決方法其實(shí)也有很多種,其實(shí)就是如何解決 Session 在多個(gè)服務(wù)器之間的共享問(wèn)題:

Session Replication

這個(gè)是最容易想到的,既然服務(wù)器 B 沒(méi)有服務(wù)器 A 存儲(chǔ)的 Session,那各個(gè)服務(wù)器之間同步一下 Session 數(shù)據(jù)不就完了。

這種方案存在的問(wèn)題也是顯而易見(jiàn)的:

  • 同步 Session 數(shù)據(jù)帶來(lái)了額外的網(wǎng)絡(luò)帶寬開(kāi)銷。只要 Session 數(shù)據(jù)有變化,就需要將數(shù)據(jù)同步到所有其他機(jī)器上,機(jī)器越多,同步帶來(lái)的網(wǎng)絡(luò)帶寬開(kāi)銷就越大。
  • 每臺(tái)Web服務(wù)器都要保存所有 Session 數(shù)據(jù),如果整個(gè)集群的 Session 數(shù)據(jù)很多(比如很多人同時(shí)訪問(wèn)網(wǎng)站的情況),每臺(tái)服務(wù)器用于保存 Session 數(shù)據(jù)的內(nèi)存占用會(huì)非常嚴(yán)重。

Session Sticky

從名稱也能看出來(lái),Sticky,即讓負(fù)載均衡器能夠根據(jù)每次的請(qǐng)求的會(huì)話標(biāo)識(shí)來(lái)進(jìn)行請(qǐng)求的轉(zhuǎn)發(fā),保證一個(gè)會(huì)話中的每次請(qǐng)求都能落到同一臺(tái)服務(wù)器上面。

存在問(wèn)題的:

  • 如果某臺(tái)服務(wù)器宕機(jī)或者重啟了,那么它上面存儲(chǔ)的 Session 數(shù)據(jù)就丟失了,用戶就需要重新進(jìn)行登陸。
  • 負(fù)載均衡器變?yōu)橐粋€(gè)有狀態(tài)的節(jié)點(diǎn),因?yàn)樗枰4?Session 到具體服務(wù)器的映射,和之前無(wú)狀態(tài)的節(jié)點(diǎn)相比,內(nèi)存消耗會(huì)更大,容災(zāi)方面會(huì)更麻煩。

Session 數(shù)據(jù)集中存儲(chǔ)

借助外部存儲(chǔ)(Redis、MySQL 等),將 Session 數(shù)據(jù)進(jìn)行集中存儲(chǔ),然后所有的服務(wù)器都從這個(gè)外部存儲(chǔ)中拿 Session

存在的問(wèn)題也很顯然:

  • 過(guò)度依賴外部存儲(chǔ),如果集中存儲(chǔ) Session 的外部存儲(chǔ)機(jī)器出問(wèn)題了,就會(huì)直接影響到我們的應(yīng)用

ThreadLocal

事實(shí)上,無(wú)論采用何種方案,使用 Session 機(jī)制,會(huì)使得服務(wù)器集群很難擴(kuò)展,因此,Session 適用于中小型 Web 應(yīng)用程序。對(duì)于大型 Web 應(yīng)用程序來(lái)說(shuō),通常需要避免使用 Session 機(jī)制。

So,在 Echo 項(xiàng)目中,我們決定摒棄 Session,一個(gè) ThreadLocal 解決所有問(wèn)題(狗頭)!

ThreadLocal 線程本地內(nèi)存,很好理解,就是每個(gè)訪問(wèn) ThreadLocal 變量的線程都有自己的一個(gè) “本地” 實(shí)例副本,每個(gè)線程之間互相隔離,互不干涉。

這里我就不詳細(xì)解釋底層原理了,ThreadLocal 適用于如下兩種場(chǎng)景:

  • 每個(gè)線程需要有自己?jiǎn)为?dú)的實(shí)例(數(shù)據(jù))
  • 實(shí)例(數(shù)據(jù))需要在多個(gè)方法中共享,但不希望被多線程共享

來(lái)看如何用 ThreadLocal 實(shí)現(xiàn)我們的需求:顯示登錄信息,在本次請(qǐng)求中持有當(dāng)前用戶數(shù)據(jù)。

首先我們需要明白的是,ThreadLocal 只跟其歸屬的線程有關(guān),線程死亡了,那么它對(duì)應(yīng)的 ThreadLocal 中存儲(chǔ)的信息也就被清除了(線程死亡前一定要釋放掉綁定的用戶數(shù)據(jù),不然會(huì)出現(xiàn) OOM 問(wèn)題),也就是說(shuō),ThreadLocal 只用于在本次請(qǐng)求中持有數(shù)據(jù)。

簡(jiǎn)單來(lái)說(shuō),我們把用戶數(shù)據(jù)存入 ThreadLocal 里,這樣,只要本次請(qǐng)求未處理完,這個(gè)線程就一直還在,當(dāng)前用戶數(shù)據(jù)就一直被持有,當(dāng)服務(wù)器對(duì)本次請(qǐng)求做出響應(yīng)后,這個(gè)線程就會(huì)被銷毀。

那同一個(gè)用戶發(fā)出的兩次請(qǐng)求可能被不同的兩個(gè)線程進(jìn)行處理,如何使得這個(gè)兩個(gè)線程的 ThreadLocal 持有相同的用戶信息呢?

過(guò)濾器。

具體來(lái)說(shuō),我們定義一個(gè)過(guò)濾器,在每次請(qǐng)求前都對(duì)用戶進(jìn)行判斷(為了避免每次請(qǐng)求都經(jīng)過(guò)過(guò)濾器,可以將登錄成功的用戶信息暫時(shí)存儲(chǔ)到 Redis 中),然后將已經(jīng)登錄成功的用戶信息存到 ThreadLocal 里,從而使得該線程在本次請(qǐng)求中持有該用戶信息。

 

責(zé)任編輯:武曉燕 來(lái)源: 飛天小牛肉
相關(guān)推薦

2013-06-24 11:16:04

移動(dòng)互聯(lián)網(wǎng)廣告盈利移動(dòng)產(chǎn)品

2023-11-07 12:03:53

機(jī)器學(xué)習(xí)目標(biāo)檢測(cè)

2015-03-18 09:54:13

內(nèi)容為王服務(wù)為王大數(shù)據(jù)

2023-10-26 06:51:29

React編譯器

2020-12-18 14:56:33

技術(shù)人工智能人臉識(shí)別

2017-11-08 11:13:14

大數(shù)據(jù)Spark數(shù)據(jù)傾斜

2016-01-08 09:48:54

IPV6網(wǎng)路協(xié)議地址

2013-05-09 10:24:28

企業(yè)軟件軟件開(kāi)發(fā)

2009-05-07 09:02:15

思科錢伯斯營(yíng)收

2019-12-06 09:50:44

QQ手機(jī)QQQQ紅包

2018-01-17 14:00:32

開(kāi)源基礎(chǔ)設(shè)施企業(yè)平臺(tái)

2021-08-15 22:58:43

手機(jī)折疊手機(jī)三星

2021-01-06 15:19:49

開(kāi)發(fā)者技能數(shù)據(jù)

2022-11-28 20:01:19

Node.js?Deno

2012-07-06 16:43:51

Linux

2017-06-14 17:03:25

微軟自然語(yǔ)言處理技術(shù)

2015-02-12 10:41:07

手機(jī)電池續(xù)航

2024-12-30 07:05:00

AI費(fèi)馬大定理人工智能

2020-12-21 14:20:13

技術(shù)資訊

2021-12-09 22:41:12

重定向程序命令
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)