成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

老舊話題:重新看看當(dāng)年感覺很難的session

beanlam / 3540人閱讀

摘要:在中,會為每個不同的用戶生成一個隨機(jī)的,每個人擁有的都是不同的。值得注意的是,過期了不代表這個文件會馬上被垃圾回收機(jī)制刪除掉,還是有可能會殘存一段時間的。

原文地址:https://t.ti-node.com/thread/...

這基本上算是個老舊的話題了,幾乎所有phper在第一次面試的時候都會被問到關(guān)于session的問題,如果不出意外,往往是如下三板斧:

php的session是什么東西

php的session存在什么地方、時候過期

php的session和cookie有什么區(qū)別

這三個問題堪稱是關(guān)于php session三大基礎(chǔ)問題了,要是掌握不好,直接導(dǎo)致面試掛掉,令人唏噓不已。

就以上三個問題簡單回顧一下:

session翻譯成中文,大抵就是會話。我們知道http協(xié)議是一個無狀態(tài)的協(xié)議,用極為粗暴的土話表示無狀態(tài)就是說“你壓根不知道這個http請求是哪個犢子發(fā)起的”或者“你永遠(yuǎn)不知道這個http請求的那頭到底是上次那個哈士奇還是上上次那個胖子”,所以為了解決這個問題,php引入session來額外標(biāo)記“到底誰發(fā)起的這個http請求”。在php中,php會為每個不同的用戶生成一個隨機(jī)的session id,每個人擁有的session id都是不同的。用戶在與服務(wù)器產(chǎn)生的每一次交互中,都是利用session id來辨別的用戶。讓php產(chǎn)生session是一件很容易的事情,直接調(diào)用session_start()函數(shù)就可以了,如下圖就是產(chǎn)生的session文件:


其中sess是文件前綴,后面的“njjf8l3lh**ff6”就是你的session id了。但是現(xiàn)在session文件內(nèi)容是空的,如果我們用如下代碼,就可以產(chǎn)生session文件的內(nèi)容:


刷新一下網(wǎng)頁,然后在再次查看原來的session文件,其中就會有如下內(nèi)容:

就是說,你往全局變量$_SESSION保存的內(nèi)容本質(zhì)上都是PHP用文本形式給你存儲到服務(wù)器上了。服務(wù)器根據(jù)你的session id讀取相應(yīng)的session文件然后把其中內(nèi)容讀出來,你就會得到你的$_SESSION數(shù)據(jù)。

php的session默認(rèn)是以文件的形式存儲的系統(tǒng)磁盤中,在運行于ubuntu 16.04系統(tǒng)的php 7.0.28中,session是存儲于/var/lib/php/sessions文件夾下,可以通過php.ini配置文件中的session.save_path來查看確定。php的過期時間是由php配置項session.gc_maxlifetime來確定的,值的單位是秒鐘,默認(rèn)是1440,也就是說當(dāng)這個session文件具體上次修改時間超過了1440秒后這個session文件就算是過期了。值得注意的是,過期了不代表這個session文件會馬上被垃圾回收機(jī)制刪除掉,還是有可能會殘存一段時間的。那么,究竟何時會被刪除?這取決于session.gc_probability和session.gc_divisor兩個配置項了。這兩個選項的比值 ( session.gc_probability / session.gc_divisor ) 就是觸發(fā)垃圾回收機(jī)制的概率,比如 ( 1 / 100 ) 就可以簡單粗暴的理解為“每產(chǎn)生100個請求,就有1次會觸發(fā)php垃圾回收機(jī)制去刪除過期的session文件”,所以你記住了:在php中如果你想要一個精確過期的session文件,最起碼默認(rèn)的session配置是絕對不可能的。話說回來,還不都是因為php并沒有啟動一個多帶帶的線程或者進(jìn)程去掃描垃圾,所以,也只能用這個“概率”這種粗暴的方式來解決這個問題,又不是不能用。

開篇說了,為了搞明白“到底是哈士奇還是胖子”的問題,不得不引入額外標(biāo)記數(shù)據(jù)才行,所以實際上,先有的cookie而有后的session,都是為了解決這個問題而產(chǎn)生的。二者的恩怨情仇在于:

cookie存在于客戶端,而session存在于服務(wù)器端,所以session相對更安全

服務(wù)器可以讀取session和cookie,但是客戶端(也就是瀏覽器)只能讀取cookie

默認(rèn)情況下,session是離不開cookie的,說到底“安全的session使用方式”必須依靠cookie才能混口飯吃。因為session id就是依靠cookie保存起來的,客戶端瀏覽器每次發(fā)送請求都會攜帶上該cookie,該cookie默認(rèn)名稱是PHPSESSID,數(shù)值就是session id。

如果說就是用不了cookie,那么session也并不是真的不能用。禁用cookie的情況下,session可以通過配置利用URL來傳遞,也就是query string直接暴露在網(wǎng)址中,非常不安全非常嚇人,嚴(yán)重不推薦這種方式,甚至應(yīng)該直接禁用!

cookie大小稍微有限制(據(jù)說考慮用localstorage代替?),session相對寬松

大概就這些,不再贅述,我是建議大家配合php.ini文件去研究上面三個問題。

如果說真的只回顧一下這三個問題,那豈不是真的應(yīng)了“一看標(biāo)題猛如虎,打開內(nèi)容1-5”?我說過了的,我這里是個正經(jīng)的博客網(wǎng)站,是個真正的有些內(nèi)涵的php文化網(wǎng)站,不能只講些個初級的內(nèi)容,是個話題都都要無論如何強(qiáng)塞點兒看起來高端的玩意進(jìn)去撐場面。

剛叨叨過了,默認(rèn)配置下session是以文本文件形保存在服務(wù)器的某個文件夾中的,有心的人應(yīng)該知道“一個目錄中文件過多是會降低讀取效率的”,所以,在用一些PC軟件的時候可以看到這些軟件會把TA需要的數(shù)據(jù)分散開來到不同的次級目錄中去。php的session文件也可以這么干,總體來說是比較簡單粗暴的。我們需要關(guān)注下兩個php配置項:

一個是session.save_handler,默認(rèn)這貨的值是“files”,也就是文件

一個是session.save_path,默認(rèn)這貨的值是一個目錄路徑,比如/var/lib/php/session。現(xiàn)在我們將這個值改成類似于session.save_path = "N;/path"這樣的,其中N是一個正整數(shù),這個數(shù)值的含義就是指將目錄分成幾個層次,比如我們修改成session.save_path = “2;/var/lib/php/sessions”,然后重啟一下apache或者fpm進(jìn)程管理器,然后執(zhí)行如下代碼:


刷新網(wǎng)頁,如下圖所示:

錯誤原因相比大家看到了,大概意思就是說“/var/lib/php/sessions/n/j/”這個文件夾不存在,那么切換到這個目錄下看看,如下圖:

果然是空的,也就說沒有/n/j這個子目錄,看來得手工創(chuàng)建了。然而,真的不能去手工創(chuàng)建,因為你哪兒知道文件夾的名字是啥?回到配置文件一頓研究,在session.save_path配置項附近發(fā)現(xiàn)如下英文字樣:

; NOTE 1: PHP will not create this directory structure automatically.
;         You can use the script in the ext/session dir for that purpose.
; NOTE 2: See the section on garbage collection below if you choose to
;         use subdirectories for session storage

英文比較蹩腳昂,大概翻譯一下,多包涵:

; NOTE 1: PHP壓根不會幫你創(chuàng)建這些文件夾,您自己個兒下載php源碼包,到ext目錄的session目中去找那個腳本去創(chuàng)建
; NOTE 2: 如果你要用子目錄存儲session的話,記得看下垃圾回收,不看就有坑。(坑在這里直接告訴大家吧,大概就是說你要自己搞子目錄存session,那我那個靠信仰和概率才能觸發(fā)的垃圾回收機(jī)制就壓根就不觸發(fā)了,你自己想辦法搞定你的過期session,我不管了)

所以呢,我們下載一個php源碼包,最好是和你運行環(huán)境版本一樣的php源碼包并解壓,命令行切到ext/session目錄下,如下圖:

看到那個mod_files.sh沒?Linux下就這腳本。mod_files.bat就是給windows用的。給這個腳本chmod +x mod_files.sh加個執(zhí)行權(quán)限,然后查看下使用方式:

為了幫助眼近視的讀者,友情翻譯一下使用方式:

./mod_files.sh "session文件根目錄" 目錄深度 哈希函數(shù)比特量
對應(yīng)我的php開發(fā)環(huán)境就是:
./mod_files.sh /var/lib/php/sessions/ 2 5
其中第一項就是你存儲session的根目錄,第二項就是那個N,第三項查看session.hash_bits_per_character配置項

然后執(zhí)行,如下圖所示:

此時到/var/lib/php/sessions中查看下,果然有目錄了,那么,再次刷新網(wǎng)頁,本以為很順利的你可能依然會遇到錯誤,如下:

session_start(): open(/var/lib/php/sessions/n/j/sess_njjf8l3lhfrpq8nrlnl1d9qff6, O_RDWR) failed: Permission denied (13)

模模糊糊認(rèn)得Permission denied這幾個字母,好像是權(quán)限的問題,難道是因為當(dāng)前apache進(jìn)程用戶或者fpm進(jìn)程用戶沒有權(quán)限往這些目錄寫數(shù)據(jù)嗎?改下這些目錄的擁有者撒,改成www-data(我系統(tǒng)中fpm的運行用戶),再試試,果然好了!

總有刁民以為這就可以解決很大的問題了,然而很悲劇的是:并不是。當(dāng)前這個方案一定程度可以解決session文件過多的問題,但是依然有兩個問題沒有得到解決:

依然是文件存儲,如果訪問量太大的話,session文件從硬盤的讀取IO或許會成為程序的瓶頸,當(dāng)然SSD速度一定會好很多

如果網(wǎng)站分別部署到了兩臺服務(wù)器上,session無法共享,出現(xiàn)故障。什么意思呢?就是為了保證高可用,網(wǎng)站程序分別在A服務(wù)器上和B服務(wù)器上,然后最外面使用一臺nginx擋在最前面做負(fù)載均衡,路人甲的某次http請求可能會被分配到A上,也可能會被分配到B上。路人甲在A上產(chǎn)生的session文件會被保存到A服務(wù)器硬盤上,但是服務(wù)器B上卻沒有,如果該用戶請求被打到B上的時候,很不幸,session丟失了,一些數(shù)據(jù)也就會丟失,路人甲八成會罵娘罵客服。也就說,A服務(wù)器和B服務(wù)器需要共享同一套session!

借此,就引入一個問題,就是分布式web部署中,如何解決session共享的問題!

關(guān)子我就不賣了,沒意思,首先想到的是redis,為A和B提供一臺C redis服務(wù)器就可以了,這樣可以“ 多快好省 ”地一舉解決問題!按照預(yù)想,引入redis后可以順利解決三個問題:

內(nèi)存級的讀寫速度,唰唰唰!

session輕松easy實現(xiàn)了共享,哪怕以后業(yè)務(wù)服務(wù)器繼續(xù)橫向擴(kuò)展到服務(wù)器D

session的過期終于可以精確到秒了,說沒就沒,不用再靠信仰和概率了

將session存入redis需要修正如下兩處php配置,首先設(shè)置session.save_handler = redis,其次是設(shè)置ession.save_path = "tcp://127.0.0.1:6379",然后重啟apache或者fpm,刷新一下網(wǎng)頁,如果網(wǎng)頁不報什么錯誤,理論上session數(shù)據(jù)就已經(jīng)到redis中去了,連接redis查看下key,如下圖:

從上至下我一共執(zhí)行了五次redis命令,分別表示:

查看所有keys從而獲取php分配給我的session文件名稱

獲取這個key的剩余時間,過期后redis該key算失效了

查看這個key的數(shù)據(jù)類型,可以看出是string類型

使用get直接獲取string的值

過了一段時間,我又刷新了一下網(wǎng)頁,然后再次用ttl看該key的剩余時間,再次被延長到1440秒了

除了redis外(memcache我就不舉例了,和redis類似),還有一種方案就是通過nfs共享來實現(xiàn),大概原理就是弄一臺服務(wù)器,通過內(nèi)網(wǎng)共享對所有php業(yè)務(wù)服務(wù)器開放讀寫,大家知道linux下磁盤是可以掛載在某個文件夾下的,所以將nfs掛載到各個php業(yè)務(wù)服務(wù)器的某個目錄下,然后按照上述文章修改響應(yīng)配置就可以了。這個,我也沒有嘗試過也懶得自己去嘗試了,所以偷個懶直接給大家拋個連接吧,是老葉博客上的一篇文章,《iMySQL | 老葉茶館,PHP實現(xiàn)多服務(wù)器session共享之NFS共享》。

裝逼完畢,如有問題,火速留言指正!

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

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/29749.html

相關(guān)文章

  • 我的WEB前端辛酸史

    摘要:在給老師做項目的這個期間,我也發(fā)現(xiàn)慕課網(wǎng),然后便貪婪的在上面學(xué)習(xí),其實現(xiàn)在看看上面的教學(xué)也是一些基礎(chǔ),想要真的學(xué)到很多,必須做實際項目,遇到問題,然后去百度或者谷歌這個問題,看別人的博客中怎么教你解決。 前言:想當(dāng)初我也是個無知騷年,學(xué)完學(xué)校的C語言基礎(chǔ)課程之后也就再也沒有什么想法了(期間還看了看JAVA,但是發(fā)現(xiàn)并不能夠?qū)W好,索性就放棄了),由于當(dāng)時期末C語言程序答辯的時候,我自己仿...

    davidac 評論0 收藏0
  • 我的WEB前端辛酸史

    摘要:在給老師做項目的這個期間,我也發(fā)現(xiàn)慕課網(wǎng),然后便貪婪的在上面學(xué)習(xí),其實現(xiàn)在看看上面的教學(xué)也是一些基礎(chǔ),想要真的學(xué)到很多,必須做實際項目,遇到問題,然后去百度或者谷歌這個問題,看別人的博客中怎么教你解決。 前言:想當(dāng)初我也是個無知騷年,學(xué)完學(xué)校的C語言基礎(chǔ)課程之后也就再也沒有什么想法了(期間還看了看JAVA,但是發(fā)現(xiàn)并不能夠?qū)W好,索性就放棄了),由于當(dāng)時期末C語言程序答辯的時候,我自己仿...

    jaysun 評論0 收藏0
  • 我的WEB前端辛酸史

    摘要:在給老師做項目的這個期間,我也發(fā)現(xiàn)慕課網(wǎng),然后便貪婪的在上面學(xué)習(xí),其實現(xiàn)在看看上面的教學(xué)也是一些基礎(chǔ),想要真的學(xué)到很多,必須做實際項目,遇到問題,然后去百度或者谷歌這個問題,看別人的博客中怎么教你解決。 前言:想當(dāng)初我也是個無知騷年,學(xué)完學(xué)校的C語言基礎(chǔ)課程之后也就再也沒有什么想法了(期間還看了看JAVA,但是發(fā)現(xiàn)并不能夠?qū)W好,索性就放棄了),由于當(dāng)時期末C語言程序答辯的時候,我自己仿...

    Darkgel 評論0 收藏0

發(fā)表評論

0條評論

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