HTTP 無狀態(tài)中的 "狀態(tài)" 到底指的是什么?

作者:賽艇隊長
博客園: cnblogs.com/bellkosmos/p/5237146.html
編輯:cnblogs_com

引子:

最近在好好了解http,發(fā)現(xiàn)對介紹http的第一句話【http協(xié)議是無狀態(tài)的茴肥,無連接的】就無法理解了:無狀態(tài)的【狀態(tài)】到底指的是什么?荡灾!

找了很多資料不僅沒有發(fā)現(xiàn)有一針見血正面回答這個問題的瓤狐,而且有些解釋還充斥了各種錯誤瞬铸,看著看著就覺得心里憋著一股濁氣吐不出來

于是在看了很多資料之后,我一口吐出濁氣础锐,大聲正面提出這個問題:http協(xié)議無狀態(tài)中的【狀態(tài)】到底指的是什么嗓节?!

然后開始不斷探索解決這個問題郁稍。赦政。。

最終很高興的是我找到了讓人滿意的答案耀怜,先賣個關(guān)子恢着,各位如果著急可以直接拉到最下查看

正文:

http協(xié)議無狀態(tài)中的【狀態(tài)】到底指的是什么?财破!

先來看這句話的另外兩個概念:(標(biāo)準的http協(xié)議是無狀態(tài)的掰派,無連接的)

  1. 標(biāo)準的http協(xié)議指的是不包括cookies, session,application的http協(xié)議左痢,他們都不屬于標(biāo)準協(xié)議靡羡,雖然各種網(wǎng)絡(luò)應(yīng)用提供商,實現(xiàn)語言俊性、web容器等略步,都默認支持它

  2. 無連接指的是什么
    每一個訪問都是無連接,服務(wù)器挨個處理訪問隊列里的訪問定页,處理完一個就關(guān)閉連接趟薄,這事兒就完了,然后處理下一個新的
    無連接的含義是限制每次連接只處理一個請求典徊。服務(wù)器處理完客戶的請求杭煎,并收到客戶的應(yīng)答后,即斷開連接

對于【無狀態(tài)】卒落,我看到很多隔著一層磨砂玻璃一樣的模糊說法(官方或者教程里的說法)羡铲,看著非常難受(但其實算是對的)

后來我發(fā)現(xiàn)我為什么覺得它看著難受了,因為他們引入了很多新的儡毕,而且明顯是一個可能用在很多地方的廣義名詞也切,這些詞最大的作用就是,混淆概念腰湾,下面我標(biāo)注了

  1. 協(xié)議對于事務(wù)處理沒有記憶能力【事物處理】【記憶能力】

  2. 對同一個url請求沒有上下文關(guān)系【上下文關(guān)系】

  3. 每次的請求都是獨立的雷恃,它的執(zhí)行情況和結(jié)果與前面的請求和之后的請求是無直接關(guān)系的,它不會受前面的請求應(yīng)答情況直接影響檐盟,也不會直接影響后面的請求應(yīng)答情況【無直接聯(lián)系】【受直接影響】

  4. 服務(wù)器中沒有保存客戶端的狀態(tài)褂萧,客戶端必須每次帶上自己的狀態(tài)去請求服務(wù)器【狀態(tài)】

我必須得到確切而具體的解釋!

這幾點給了我下一步思考的方向:

  1. 【服務(wù)器中沒有保存客戶端的狀態(tài)葵萎,客戶端必須每次帶上自己的狀態(tài)去請求服務(wù)器 】這里的客戶端的狀態(tài)是不是確切地指服務(wù)器沒有保存客戶的信息呢导犹?但顯然不是啊

  2. 【HTTP無狀態(tài)的特性嚴重阻礙了這些應(yīng)用程序的實現(xiàn)唱凯,畢竟交互是需要承前啟后的,簡單的購物車程序也要知道用戶到底在之前選擇了什么商品】我對此質(zhì)疑為什么無狀態(tài)就不能實現(xiàn)購物車呢谎痢?服務(wù)器就不能存儲東西了么磕昼?

  3. 【 每次的請求都是獨立的,<它的執(zhí)行情況和結(jié)果>與<前面的請求>和<之后的請求>是無直接關(guān)系的】我覺得這個說法比較靠譜节猿,但是所謂的不同請求間的沒有關(guān)系票从,是指的請求內(nèi)容沒有關(guān)系,還是只是指請求本身沒有關(guān)系滨嘱?
    請求內(nèi)容沒有關(guān)系只可能是服務(wù)器上不存有用戶數(shù)據(jù)才可能啊峰鄙,但是顯然是存有的啊
    請求本身沒有關(guān)系,這又有什么意義呢太雨,每一次的請求有什么價值吟榴?

根據(jù)這個方向我做了一個模擬訪問實驗:假如沒有cookie沒有session,只有http的時候囊扳,那當(dāng)一個注冊用戶訪問這個購物網(wǎng)站的時候吩翻,會發(fā)生這些事情:

前提情況:

服務(wù)器肯定為每個注冊用戶建立了數(shù)據(jù)表,記錄用戶的數(shù)據(jù)
http是無連接的

第一步需要登錄
用戶通過http把用戶的用戶名和密碼發(fā)送給服務(wù)器锥咸,服務(wù)器把他們跟自己存有的用戶資料對比狭瞎,如果一致,則返回信息登錄成功

然后用戶點擊某一商品頁

  1. 這個動作相當(dāng)于輸入一個商品頁的網(wǎng)址

  2. 假如商品頁比較機密不對外公開搏予,需要是用戶才能訪問

  3. 而雖然http能傳送用戶名和密碼熊锭,而且剛才也輸入了,還驗證成功了缔刹,但是因為服務(wù)器既不會記得你登錄的狀態(tài)球涛,你的客戶端也不會存儲你剛才輸入的用戶名和密碼

  4. 所以因為這一次訪問因為無法確定你的身份劣针,只能訪問失敗
    這時候如果要解決這個問題校镐,而且沒有cookie沒有session,那就只能你在訪問網(wǎng)址的同時繼續(xù)帶上你的用戶名和密碼(繼續(xù)輸入咯)其實就像我現(xiàn)在的APP一樣

假設(shè)上一步的問題解決了捺典,就是每次訪問的時候都會手動輸入用戶名和密碼鸟廓,然后現(xiàn)在的情況是:你已經(jīng)選了幾件商品在你的購物車中,你想再添加一件商品襟己,于是你點擊某個商品旁邊的加號

這個動作也相當(dāng)于輸入一個網(wǎng)址引谜,網(wǎng)址的內(nèi)容是發(fā)送一個請求,往你的購物車中加入這個商品

系統(tǒng)首先用你傳來的用戶名和密碼驗證你的身份擎浴,然后訪問你的數(shù)據(jù)庫员咽,在其中的購物車屬性下加一條數(shù)據(jù),就是這個商品的數(shù)據(jù)

操作結(jié)束后贮预,返回操作成功贝室,并結(jié)束訪問

OK契讲,實驗結(jié)束,看似沒有cookie沒有session也能湊合解決問題滑频,其實兩個操作都有很大的問題

  1. 你每訪問一次需要權(quán)限的內(nèi)容都需要在客戶端輸入用戶名和密碼捡偏,這一項的繁瑣就不必贅述了

  2. 你的每一次操作都要與系統(tǒng)底層的數(shù)據(jù)庫進行交互
    多次少量的訪問存在非常大的性能浪費。非常容易就能想到肯定是一次大量的操作更加有效率峡迷,于是就想到了緩存區(qū)

  3. 你的非重要瑣碎數(shù)據(jù)也被寫進數(shù)據(jù)庫中银伟,跟你的主要數(shù)據(jù)放在一起
    一次次添加和刪除購物車其實只是跟你這次瀏覽,或者叫這次會話有關(guān)绘搞,是臨時的數(shù)據(jù)彤避,跟用戶的主要信息無關(guān),它們沒什么價值夯辖,純粹的冗余數(shù)據(jù)(不排除現(xiàn)在有的公司覺得這種數(shù)據(jù)也有非常大的價值可以讓它們巧妙的利用)忠藤,用什么存放這些臨時的數(shù)據(jù),我們也很容易想到緩存區(qū)

經(jīng)過這個模擬訪問實驗楼雹,結(jié)合前面的思考方向模孩,我們知道了三點:

服務(wù)器上肯定存有用戶的數(shù)據(jù),你提交的增刪改查它也能夠處理贮缅,所以這句話中【服務(wù)器中沒有保存客戶端的狀態(tài)】的狀態(tài)并不是指用戶的數(shù)據(jù)榨咐,我們的猜測不對

我們的質(zhì)疑對了,無狀態(tài)能實現(xiàn)購物車谴供,可以通過服務(wù)器上存有的用戶數(shù)據(jù)來實現(xiàn)

但是块茁,使用上面這種方式實現(xiàn)購物車,存在三個比較大的問題桂肌。由此数焊,我們不禁會想,這三個問題的解決是不是跟我們不確切了解的【狀態(tài)】一詞有關(guān)崎场?于是佩耳,接下來我們來通過解決這三個問題來把【狀態(tài)】的意義探尋下去

由上所述,我們可以在http的基礎(chǔ)上增加一些機制來解決上面出現(xiàn)的三個問題

  1. 在用戶端增加一個記錄本是非常有必要的谭跨,正好官方加入的cookie機制跟這個一樣干厚,它的用處也確實是上面討論的那樣,一般就是用來標(biāo)識訪問者的身份

  2. 在服務(wù)器增加一個緩存區(qū)能同時解決后兩個問題
    有了這個緩存區(qū)作為一個數(shù)據(jù)緩沖螃宙,就不用一次次地訪問數(shù)據(jù)庫蛮瞄,浪費大量計算機資源,而是在最后統(tǒng)一歸入數(shù)據(jù)庫
    有了這個緩存區(qū)谆扎,你就不用把臨時的數(shù)據(jù)放到數(shù)據(jù)庫中了挂捅,只需要在你們交流告一段落之后,再把數(shù)據(jù)整理堂湖,把有用的數(shù)據(jù)歸入數(shù)據(jù)庫

  3. 這里就自然引申出了一個重要的概念:會話闲先,它作為一個緩沖存儲區(qū)被從數(shù)據(jù)庫中分離出來周瞎,理由并不生硬,它有其獨特的重要且不可替代的作用饵蒂。這個東西恰好跟官方加入的session機制一樣

另外說一個非常具有迷惑性的容易讓人對session的主要作用產(chǎn)生偏離的理解:認為session存在的價值就是給訪問者分配一個sessionID代替用戶名和密碼

為什么非常具有迷惑性声诸,因為session確實做了這件事,而且也起到了很大的作用退盯,所以它是對的彼乌,但是只對一半,而且沒有涉及問題的本質(zhì)渊迁,這種情況是最危險的(看似很有說服力慰照,把你說服了,所以你很難有動力繼續(xù)找下去琉朽,但是真實情況跟它有偏差毒租,但是偏差不大,所以又很難把你說服回來箱叁,只有隱隱的不對勁墅垮,這個時候你離真實最近,也離真實最遠)

那就順便說說它為什么是對的耕漱,也就是用session做的另一件有用的事:

給每個session一個ID算色,一方面用來方便自己查詢,另一方面把這個ID給用戶螟够,用戶下一次訪問的時候就可以不用用戶名和密碼灾梦,而是直接使用這個ID來表明自己的身份

首先,這個ID安全嗎妓笙?這個ID比直接傳用戶名和密碼安全嗎若河?

你很容易會想到,本來用戶名和密碼的組合還特地設(shè)置地比較復(fù)雜寞宫,你這換一組數(shù)字就代替了萧福,是不是太不安全了?
我們知道http協(xié)議本身是完全不加密的淆九,如果使用用戶名和密碼统锤,第一次訪問是放在http頭中毛俏,后邊自動保存了密碼就會放在cookie中炭庙,這些都完全沒有加密,它的安全性基本為0煌寇,就是裸奔了焕蹄,只要被竊取,那就丟失了
所以阀溶,就這個意義來講腻脏,sessionID的安全性跟使用用戶名和密碼沒什么區(qū)別
但是其實鸦泳,雖然http本身不能加密,但是有些軟件什么的永品,能在應(yīng)用層面手動給你加密做鹰,比如QQ就會使用戶名密碼加臨時驗證碼聯(lián)合哈希,sessionID加一個時間戳簡單加密也是非常常用的方法
而且因為sessionID本身有有效期鼎姐,即使丟了钾麸,也可能很快失效,造成的損失可能沒那么大炕桨,而用戶名跟密碼丟了饭尝,那就大了
所以總結(jié)就是:不嚴格加密的sessionID和用戶名和密碼一樣,都不太安全献宫;但是相比較來說钥平,sessionID要安全一些;而使用https是完全安全的

然后姊途,使用sessionID有哪些好處涉瘾?
方便直接根據(jù)ID查詢用戶對應(yīng)的session
加密的時候計算量小
安全性不會降低,甚至還更高一些

OK捷兰,通過獨立地解決純http機制會產(chǎn)生的問題睡汹,我們探討了cookie和session機制的本質(zhì)。

而且想到:【使用http協(xié)議寂殉,服務(wù)器中不會保存客戶端的狀態(tài)】所產(chǎn)生的問題通過增加cookie和session機制解決了囚巴,是不是就意味著這個【狀態(tài)】跟cookie和session的關(guān)系非常緊密?

所以這個無狀態(tài)指的是【沒有對 本次會話 設(shè)置一個緩存區(qū)友扰,記錄這次會話的狀態(tài)彤叉,緩存區(qū)包括服務(wù)器端和用戶端】但好像還是沒有點破關(guān)鍵(主要是覺得跟前面那些官方對狀態(tài)的說法不太吻合,甚至沒有對應(yīng)關(guān)系)

忽然我想到一個問題:一個有狀態(tài)的http是什么樣的村怪?

很難直接想象有狀態(tài)的http是什么樣秽浇,因為http這種機制是天然無狀態(tài)的

那就類比一下吧,另一個天然有狀態(tài)的機制叫TCP

如果有狀態(tài)的意思是它的每次請求是有聯(lián)系的甚负,那么有狀態(tài)的TCP的樣子是:假如一份數(shù)據(jù)分了三份TCP包發(fā)送柬焕,那這個包上面會標(biāo)明這是第幾個包,會標(biāo)明這個包跟那幾個包是有聯(lián)系的梭域,有什么聯(lián)系

但好像這個有狀態(tài)的TCP跟我們想要的有狀態(tài)的HTTP沒有關(guān)系斑举,因為即使每次http請求之間互相有聯(lián)系,它也不能解決上面提到的http無狀態(tài)的問題

誒病涨,等等富玷,好像能類比:

假如每個http連接都有一個簽名,于是第一次登陸成功之后,服務(wù)器就知道了這個簽名是允許登陸的赎懦,于是之后所有同樣簽名的http連接都能登陸雀鹃,這里利用了同一個用戶發(fā)出的http連接之間的同主人關(guān)系,這里解決了一個保持登錄狀態(tài)的問題

同樣励两,來嘗試利用這個【每次http請求之間互相有聯(lián)系】來解決上面碰到的那個問題【每一次操作都要與系統(tǒng)底層的數(shù)據(jù)庫進行交互】黎茎,但想了半天確實無法進行下去

不過我靈機一動,從另一個角度來想当悔,好像解決了這個問題:

  1. 只有【每次http請求之間互相有聯(lián)系】這個條件工三,無法解決【每一次操作都要與系統(tǒng)底層的數(shù)據(jù)庫進行交互】

  2. 因為很明顯,要解決【每一次操作都要與系統(tǒng)底層的數(shù)據(jù)庫進行交互】就必須在服務(wù)器端開辟一塊緩存區(qū)

  3. 不過如果你思考一下如何實現(xiàn)【每次http請求之間互相有聯(lián)系】先鱼,你就會發(fā)現(xiàn)俭正,它也需要在服務(wù)器端開辟一塊緩存區(qū)

  4. 所以【在服務(wù)器端開辟一塊緩存區(qū)】才是真正的條件,也就是說焙畔,它確實等價于【有狀態(tài)】

  5. 而且我也找到了這個【在服務(wù)器端開辟一塊緩存區(qū)】的條件跟前面那些官方對狀態(tài)的說法對應(yīng)的點掸读,那就是:

通過在服務(wù)器端開辟一塊緩存區(qū),存儲宏多、記憶儿惫、共享一些臨時數(shù)據(jù),你就可以:

協(xié)議對于事務(wù)處理有記憶能力【事物處理】【記憶能力】

對同一個url請求有上下文關(guān)系【上下文關(guān)系】

每次的請求都是不獨立的伸但,它的執(zhí)行情況和結(jié)果與前面的請求和之后的請求是直接關(guān)系的【不獨立】【直接關(guān)系】

服務(wù)器中保存客戶端的狀態(tài)【狀態(tài)】

所以肾请,這個狀態(tài),加上前面說的客戶端也有cookie更胖,就是指铛铁,客戶端和服務(wù)器在臨時會話中產(chǎn)生的數(shù)據(jù)!而前面也說道了却妨,使用緩存區(qū)保存臨時會話中的數(shù)據(jù)是多么重要

所以狀態(tài)不僅包括不同URL訪問之間的關(guān)系饵逐,還有對其他URL訪問的數(shù)據(jù)記錄,還有一些其他的東西彪标,所以更確切地說倍权,狀態(tài)應(yīng)該是【實現(xiàn)了這些東西所憑借的后面的緩存空間】中的客戶的臨時數(shù)據(jù)

cookie和session應(yīng)該是完全實現(xiàn)了有狀態(tài)這個功能

一種常見的對狀態(tài)的誤解:

  1. 有人在解釋HTTP的無狀態(tài)時,把它跟有連接對立捞烟,說是兩種方式薄声,也就是如果想不無狀態(tài),就必須有連接题画,但其實不然

  2. 有連接和無連接以及之后的Keep-Alive都是指TCP連接

  3. 有狀態(tài)和無狀態(tài)可以指TCP也可以指HTTP

  4. TCP一直有狀態(tài)默辨,HTTP一直無狀態(tài),但是應(yīng)用為了有狀態(tài)婴程,就給HTTP加了cookie和session機制廓奕,讓使用http的應(yīng)用也能有狀態(tài)抱婉,但http還是無狀態(tài)

  5. 開始TCP是有連接档叔,后來TCP無連接桌粉,再后來也就是現(xiàn)在TCP是Keep-Alive,有點像有連接

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末衙四,一起剝皮案震驚了整個濱河市铃肯,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌传蹈,老刑警劉巖押逼,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異惦界,居然都是意外死亡挑格,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進店門沾歪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來漂彤,“玉大人,你說我怎么就攤上這事灾搏〈焱” “怎么了?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵狂窑,是天一觀的道長媳板。 經(jīng)常有香客問我,道長泉哈,這世上最難降的妖魔是什么蛉幸? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮丛晦,結(jié)果婚禮上巨缘,老公的妹妹穿的比我還像新娘。我一直安慰自己采呐,他們只是感情好若锁,可當(dāng)我...
    茶點故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著斧吐,像睡著了一般又固。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上煤率,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天仰冠,我揣著相機與錄音,去河邊找鬼蝶糯。 笑死洋只,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播识虚,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼肢扯,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了担锤?” 一聲冷哼從身側(cè)響起蔚晨,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎肛循,沒想到半個月后铭腕,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡多糠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年累舷,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片夹孔。...
    茶點故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡被盈,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出析蝴,到底是詐尸還是另有隱情害捕,我是刑警寧澤,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布闷畸,位于F島的核電站尝盼,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏佑菩。R本人自食惡果不足惜盾沫,卻給世界環(huán)境...
    茶點故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望殿漠。 院中可真熱鬧赴精,春花似錦、人聲如沸绞幌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽莲蜘。三九已至谭确,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間票渠,已是汗流浹背逐哈。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留问顷,地道東北人昂秃。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓禀梳,卻偏偏與公主長得像,于是被迫代替她去往敵國和親肠骆。 傳聞我的和親對象是個殘疾皇子算途,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,700評論 2 354