国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

對PHP SESSION的深刻認識

wupengyu / 1713人閱讀

摘要:而這個就是作為客戶端的唯一標識而存在的即使在同一臺電腦上,瀏覽器和瀏覽器對于服務(wù)器來說都是不同的客戶端。當然,這個名不是固定的,我們可以在文件中的項進行修改。文件的命名格式是的值。比如說,的值是,是一個長度為的字符串。

前言:
在不久之前,本人去參加了某公司的實習面試,其中面試官問我關(guān)于 SESSION 實現(xiàn)的原理,當時我就懵逼了,因為在之前的開發(fā)中,我只知道 session 與 cookie 的區(qū)別在于:session 是保存在服務(wù)器端,cookie 保存在客戶端。那 session 在服務(wù)端是怎么樣保存的?session_id 又是什么?等等。我當時答不上來。回來后決定把這些搞懂。

為什么要使用 SESSION?
是因為目前網(wǎng)絡(luò)中所使用的http協(xié)議造成的,http協(xié)議是無狀態(tài)協(xié)議,通俗點說就是當你發(fā)送一次請求道服務(wù)器端,然后再次發(fā)送請求到服務(wù)器端,服務(wù)器是不知道你的這一次請求和上一次請求是來源于同一個人發(fā)送的。而 session 就能很好解決這個問題。

在我們的訪問期間,各個頁面間共享的數(shù)據(jù)放在session中,就比如說我們的登陸信息,如果沒有 session 的話,當你在這個頁面登陸之后,在點擊下一個頁面的時候你需要再次登陸。

引入:
現(xiàn)在我們來看看平時我們是怎么使用 session 的,大家看下面的例子


現(xiàn)在我們在瀏覽器 A 打開

http://localhost/index.php?user=lsgogroup;

返回:

array(1){["user"]=>string(9)"lsgogroup"}

在瀏覽器 B 打開

http://localhost/index.php

返回:

array(1){["user"]=>string(7)"default"}

問題:

session_start() 的作用是什么?
為什么在瀏覽器 B 中返回的不是:

array(1){[“user”]=>string(9)“l(fā)sgogroup”} ?

$_SESSION 數(shù)組是怎么保存這些數(shù)據(jù)的?
理解 PHP SESSION 機制:
session 機制是一種服務(wù)器端的機制,服務(wù)器使用一種類似于散列表的結(jié)構(gòu)來保存信息。

當程序需要為某個客戶端的請求創(chuàng)建一個 session 的時候,服務(wù)器首先檢查這個客戶端的請求(Http Request)里是否已包含了一個 session 標識-稱為 sessionid,如果已包含一個 sessionid 則說明以前已經(jīng)為此客戶端創(chuàng)建過 session,服務(wù)器就按照 sessionid 把這個 session 檢索出來使用,如果客戶端請求不包含 sessionid,則為此客戶端創(chuàng)建一個 session 并且生成一個與此 session 相關(guān)聯(lián)的 sessionid,sessionid的值應(yīng)該是一個既不會重復,又不容易被找到規(guī)律以仿造的字符串,這個 sessionid 將被在本次響應(yīng)中返回給客戶端保存。而這個 sessionid 就是作為客戶端的唯一標識而存在的(即使在同一臺電腦上,瀏覽器 A 和瀏覽器 B 對于服務(wù)器來說都是不同的客戶端)。

上面一段話你可能暫時不會理解,不過不要緊,我會在下面作出解釋:

現(xiàn)在我們來看看瀏覽器 A 和 瀏覽器 B 的 cookie:

瀏覽器 A (這里對應(yīng)是谷歌瀏覽器):

瀏覽器 B (這里對應(yīng)是火狐瀏覽器) :

對比可以看到,兩個瀏覽器對于 localhost 都有一條名為 PHPSESSID 的 cookie 記錄,而這個 PHPSESSID 就是上面所說的 sessionid,它告訴服務(wù)器請求是來自瀏覽器 A 還是瀏覽器 B 。

現(xiàn)在我們可以回答上面的問題 2 了:

由于瀏覽器 A 的 PHPSESSID 和瀏覽器 B 的 PHPSESSID 是不一樣的,因此服務(wù)器根據(jù) sessionid 檢索 session 的數(shù)據(jù)也是不一樣的,也就是說瀏覽器 A 請求的 $_SESSION 數(shù)組和 瀏覽器 B 請求的 $_SESSION 數(shù)組也是不一樣的。

(當然,PHPSESSID 這個 id 名不是固定的,我們可以在 php.ini 文件中的 session.name 項進行修改。)

上面的例子是使用 COOKIE 保存 PHPSESSID,但是,由于 cookie 可以被人為的禁止,必須有其他機制以便在 cookie 被禁止時仍然能夠把 sessionid 傳遞回服務(wù)器。有兩種技術(shù)可以解決這個問題:

URL重寫,就是把 sessionid 直接附加在URL路徑的后面:

http://localhost/index.php?user=lsgogroup&PHPSESSID=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng

隱藏表單傳遞。
由于這不是重點,這里不展開講。

SESSION 是怎么存儲數(shù)據(jù)的?
答:session 是以文件的形式保存的。

php.ini 中的配置項 session.save_handler = files;
默認為 file,定義 session 在服務(wù)端的保存方式,file 意為把 session 保存到一個臨時文件里。

php.ini 中的配置項 session.save_path= “”;
這個里面填寫的路徑,將會使session文件保存在該路徑下。

session 文件的命名格式是:“sess_[PHPSESSID的值]”。每一個文件,里面保存了一個會話的數(shù)據(jù)。

我們查看服務(wù)器端 session.save_path 目錄會發(fā)現(xiàn)很多類似 sess_vv9lpgf0nmkurgvkba1vbvj915 這樣的文件,這個其實就是 sessionid(也就是 PHPSESSID) “vv9lpgf0nmkurgvkba1vbvj915″ 對應(yīng)的數(shù)據(jù)。真相就在這里,客戶端將 sessionid 傳遞到服務(wù)器,服務(wù)器根據(jù) sessionid 找到對應(yīng)的文件,讀取的時候?qū)ξ募?nèi)容進行反序列化就得到 session 的值($_SESSION數(shù)組中的數(shù)據(jù)),保存的時候先序列化再寫入。

由于我做實驗的時候使用的是 ubuntu 系統(tǒng),因此我的 session.save_path 默認實在 /var/lib/php/sessions 下,我們來看看前面瀏覽器 A 生成的 session 文件是怎樣的(瀏覽器 A 的 PHPSESSID = ‘nqqleletmsb0nuf7d4ulvotk45’):

cd /var/lib/php/sessions
#由于session數(shù)據(jù)是很重要的數(shù)據(jù),因此必須只能 root 用戶才能打開
sudo vim sess_nqqleletmsb0nuf7d4ulvotk45
#看看文件格式是不是 "sess_[PHPSESSID的值]"

文件內(nèi)容:

user|s:9:"Jodieeeee";

從文件內(nèi)容可以看到,數(shù)據(jù)是經(jīng)過序列化的,數(shù)據(jù)的讀取規(guī)則是這樣的:

每一個session的值是以分號";"分開的。比如”user|s:9:“Jodieeeee”;“就是一個完整的session值結(jié)束,如果再添加 $_SESSION[‘name’]=“LSGOZJ”,則變成這樣 ”user|s:9:“Jodieeeee”;name|s:7:“LSGOZJ”;“
里面的讀取規(guī)則:符號“|”前面表示 session 名稱。符號后面是該 session 的具體信息。包括:數(shù)據(jù)類型,字符長度,內(nèi)容。比如說 ”user|s:9:“Jodieeeee”;“,$_SESSION[‘user’] 的值是 “Jodieeeee”,是一個長度為 9 的字符串。
等等。。。
到了這里,我們就解決了上面的問題 3 了。

其實還有很多種存儲session的方式,如果我們想自定義別的方式保存(比如用數(shù)據(jù)庫),則需要把該項設(shè)置為 user;我們還可以使用 memcache、redis 等優(yōu)秀的緩存系統(tǒng)(前提是你的服務(wù)器安裝了此類軟件)。

session_start()函數(shù)的作用是什么?
了解的原理之后,所謂的 session 其實就是客戶端一個 sessionid 對應(yīng)服務(wù)器端一個 session file,新建session 之前執(zhí)行 session_start() 是告訴服務(wù)器要種一個 cookie 以及準備好 session 文件,要不然你的session 內(nèi)容怎么存;讀取 session 之前執(zhí)行 session_start() 是告訴服務(wù)器,趕緊根據(jù) sessionid 把對應(yīng)的 session 文件反序列化。

說白了,當我們使用 php 的內(nèi)置函數(shù) session_start( ) 的時候,就是到服務(wù)器的指定的磁盤目錄把 session 數(shù)據(jù)載入,實際上就是拿類似 sess_74dd7807n2mfml49a1i12hkc45 的文件。

只有一個 session 函數(shù)可以在 session_start() 之前執(zhí)行,session_name():讀取或指定 session 名稱(比如默認的就是”PHPSESSID”),這個當然要在session_start之前執(zhí)行。

根據(jù) http 的請求機制,當瀏覽器請求的時候,頭部信息會把瀏覽器中的 cookie 一起發(fā)給服務(wù)器。PHPSESSID 這個 cookie 也是在其中發(fā)給了服務(wù)器,php 引擎通過讀取 PHPSESSID 的值來確定要載入哪個 session 文件。

比如值為 74dd7807n2mfml49a1i12hkc45,載入的就是"sess_74dd7807n2mfml49a1i12hkc45"。

注:當你調(diào)用 php 的函數(shù) session_start(),才表明你需要使用 session 文件了。不然平白無故就去載入文件,浪費性能。

SESSION 的清理:
在平時我們談?wù)?SESSION 的機制的時候,常常聽到這樣一種誤解“只要關(guān)閉瀏覽器,session就消失了”(本人也是一度認為這樣),其實可以想象一下會員卡的例子,除非顧客主動對店家提出銷卡,否則店家絕對不會輕易刪除顧客的資料。

對 session 來說也是一樣的,除非程序通知服務(wù)器刪除一個 session,否則服務(wù)器會一直保留,程序一般都是在用戶做 logoff (注銷操作,類似于 session_destroy()操作)的時候發(fā)個指令去刪除 session。然而瀏覽器從來不會主動在關(guān)閉之前通知服務(wù)器它將要關(guān)閉,因此服務(wù)器根本不會有機會知道瀏覽器已經(jīng)關(guān)閉,之所以會有這種錯覺,是大部分 session 機制都使用會話 cookie 來保存 sessionid ,而關(guān)閉瀏覽器后這個sessionid就消失了,再次連接服務(wù)器時也就無法找到原來的session,但是服務(wù)器上對應(yīng)的 session file 依然存在。

為什么關(guān)閉瀏覽器后 sessionid 就會消失呢?這跟 cookie 在客戶端的存儲有關(guān),如果在設(shè)置 cookie 的時候沒有指定生命周期,那么 cookie 的數(shù)據(jù)是存儲在內(nèi)存中的,當瀏覽器被關(guān)閉,內(nèi)存被回收了,那么cookie 也就沒有了(這就是為什么cookie在沒有指定生命周期的時候,其生命周期與瀏覽器生命周期一樣)。

如果服務(wù)器設(shè)置的 cookie 被保存到硬盤上(設(shè)置了生命周期),或者使用某種手段改寫瀏覽器發(fā)出的HTTP請求頭,把原來的 sessionid 發(fā)送給服務(wù)器,則再次打開瀏覽器仍然能夠找到原來的session。

恰恰是由于關(guān)閉瀏覽器不會導致 session 被刪除,迫使服務(wù)器為 seesion 設(shè)置了一個失效時間,當距離客戶端下一次使用 session 的時間超過這個失效時間時,服務(wù)器就可以認為客戶端已經(jīng)停止了活動,才會把session 刪除以節(jié)省存儲空間。

我們來看看服務(wù)器是怎樣刪除 session 數(shù)據(jù)的:

session.gc_probability = 1

session.gc_divisor = 100

session.gc_maxlifetime = 1440

這三個配置項組合構(gòu)建服務(wù)端 session 的垃圾回收機制。

session.gc_probability 與 session.gc_divisor 構(gòu)成執(zhí)行 session 清理的概率,理論上的解釋為服務(wù)端定期有一定的概率調(diào)用 gc(garbage collection 垃圾回收) 進程來對 session 進行清理,清理的概率為:gc_probability/gc_divisor 比如:1/100 表示每一個新會話初始化時,有 1% 的概率會啟動垃圾回收程序,清理的標準為 session.gc_maxlifetime 定義的時間(清理過期的數(shù)據(jù))。

我所用的系統(tǒng)是ubuntu,php.ini 中指定的 session.gc_probability = 0,也就是概率為零,原因是該系統(tǒng)是使用 cron 腳本來執(zhí)行垃圾清理的。

后話:
session 還有很多需要整理和學習的地方,如:

session多服務(wù)器共享的問題,假如有多臺php服務(wù)器進行負載均衡的時候,用戶登錄時訪問的是第一臺服務(wù)器,沒準下一個頁面訪問的是第二臺服務(wù)器,但是 session 數(shù)據(jù)是存儲在第一臺服務(wù)器上的,因此在訪問下一個頁面的時候由于沒有 session 數(shù)據(jù)(第二臺服務(wù)器上)導致用戶必須重新登陸。
從上面的分析我們也知道,php 中 session 默認通過文件的方式實現(xiàn),但是如果訪問量大,可能產(chǎn)生的 SESSION 文件會比較多,從眾多的文件中選擇其中一個文件不是一件輕松的事情,而且每次都以打開文件、讀取文件的方式,也會產(chǎn)生大量的 I/O 操作,嚴重影響服務(wù)器的性能。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/31338.html

相關(guān)文章

  • gson-plugin告別Json數(shù)據(jù)類型不一致(一)

    摘要:六原理說明侵入編譯流程,在編譯過程中,修改庫的字節(jié)碼,修改解析相關(guān)的方法,在數(shù)據(jù)類型不一致的時候,跳過當前字段的解析。 一、目錄 1.gson-plugin告別Json數(shù)據(jù)類型不一致(一)2.gson-plugin基礎(chǔ)源碼分析(二)3.gson-plugin深入源碼分析(三)4.gson-plugin如何在JitPack發(fā)布(四) 看完這4篇文章,對Gson解析會有更加深刻的認識,對A...

    canopus4u 評論0 收藏0
  • php 面試題目整理(持續(xù)更新)

    摘要:來自博客整理于面試別人或被別人面試的一些題目持續(xù)更新答案網(wǎng)上基本都有,不一一列舉。例有個人去游玩,需要買水,商店活動買瓶贈送一瓶。請問題目至少需要買多少瓶飲料才可以人手一瓶前端方面前端性能團隊總結(jié)的條黃金定律說出幾條 來自 AT博客整理于面試別人或被別人面試的一些題目(持續(xù)更新),答案網(wǎng)上基本都有,不一一列舉。希望能幫到需要換工作的你。 數(shù)據(jù)庫 mysql 索引的理解 mysql b...

    missonce 評論0 收藏0
  • php 面試題目整理(持續(xù)更新)

    摘要:來自博客整理于面試別人或被別人面試的一些題目持續(xù)更新答案網(wǎng)上基本都有,不一一列舉。例有個人去游玩,需要買水,商店活動買瓶贈送一瓶。請問題目至少需要買多少瓶飲料才可以人手一瓶前端方面前端性能團隊總結(jié)的條黃金定律說出幾條 來自 AT博客整理于面試別人或被別人面試的一些題目(持續(xù)更新),答案網(wǎng)上基本都有,不一一列舉。希望能幫到需要換工作的你。 數(shù)據(jù)庫 mysql 索引的理解 mysql b...

    Tony_Zby 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<