SESSION機制

一:Session與Cookie

Session:在服務器端創建並存放在服務器的內存中的,Session的內容存儲是鍵值對的列表,格式:名稱 | 類型:長度:值 
Session的生命週期:在php.ini中 session.gc_maxlifetime 爲session設置了生存時間(默認爲1440s) 客戶端關閉瀏覽器,不會影響服務器端對session的存儲。

Cookie:在服務器端創建並寫回到客戶端瀏覽器,Cookie是http標頭的一部分,瀏覽器接到響應頭中關於寫Cookie的指令則在本地臨時文件夾中,創建了一個cookie文件,用來保存的Cookie內容。Cookie內容的存儲是鍵值對的方式 。

Cookie的生命週期:可以設置過期時間,如果不設置則是會話級別的,即關閉瀏覽器就會消失。

二:執行過程

        1.  過程:瀏 覽器首次訪問服務器,如果是登陸類型的網站,發送請求如果沒有帶身份,服務器檢測不到cookie會跳轉到登錄窗口,輸入用戶名和密碼後再次請求,用戶信 息後驗證通過後返回請求頁,並在HTTP頭中添加setcookie信息,瀏覽器接受到返回內容後會處理http頭部的相應信息,這裏會設置 cookie,第二次用戶訪問服務器時會瀏覽器會自動把cookie內容讀取出來並加到http頭部,服務器接受請求後驗證提交過來的 cookies是否正確,正確直接就返回相應的頁面,不正確則返回登錄頁面,其中會話是指從一個瀏覽器窗口打開到關閉這個期間。

        2. 原理: PHP默認的Session是基於Cookie的,在此期間首先調用session_start()函數,Session會先判斷當前$_COOKIE[session_name()]是否有值(session_name()返回保存session_id的COOKIE鍵名),這個值可以從php.ini找到 session.name = PHPSESSID(默認值PHPSESSID)。如果沒有值,函數會創建一個唯一的SessionID,同時通過header頭(header(‘Set-Cookie: session_name()=session_id(); path=/’)) 將SessionID保存到客戶端的Cookie中,並且在服務器端生成Session文件,文件名規則是:sess_SESSION_ID(例 如:sess_sgj1k9pq1220g5l6ne283teld1,一個128位的哈希值),Session變量的值經php內部系列化後保存在服務 器機器上的文本文件中和客戶端的變量名(默認情況下)爲PHPSESSID的Cookie進行對應交互。當再訪問這個網站其他頁面時將通過http請求頭 將客戶端的Cookie中保存的SessionID攜帶過來,這時session_start()函數不會再分配新的SessionID而是在服務器端尋 找和這個SessionID 同名的Session文件將之前保存的信息取出來。

        3. 依賴性:PHP 中的Session在默認情況下是使用客戶端的Cookie來保存session_id的,所以當客戶端的Cookie出問題或者禁用的時候就會影響 Session的使用了。但是Session不一定必須依賴cookie。當客戶端的Cookie被禁用或出現問題時,PHP會自動把 session_id附着在url中,這樣再通過session_id就能跨頁使用Session變量了。這種附着也是有一定條件的,即“php.ini 中的session.use_trans_sid = 1或者編譯時打開打開了--enable-trans-sid選項”。但是PHP5只能在Linux平臺可以自動檢測Cookie的狀態而在window 平臺上沒有此功能。

三:Session的自動回收機制

    session_start() 是Session機制的開始,它有一定概率開啓垃圾回收,因爲Session是存放在文件中,PHP自身的垃圾回收是無效的,Session的回收是要刪 文件的,這個概率是根據php.ini的配置決定的,有的系統的設置是 session.gc_probability =0,也就是概率是0,而是通過cron或者是其他腳本來實現垃圾回收。默認配置是:

1 session.gc_probability =12 session.gc_divisor     =1003 session.gc_maxlifetime =1440

過期時間 默認24分鐘,概率是 session.gc_probability/session.gc_divisor 結果 1/100,即session_start()函數被調用1000次纔會有一次調用垃圾回收程序,所以頁面訪問越頻繁概率就越小,建議值是1/(1000~5000)。不建議設置過小,因爲session的垃圾回收,是需要檢查每個文件是否過期的。

      客戶端的Cookie的過期機制:失效了瀏覽器自然發送不了cookie到服務器,這時即使服務器的Session文件存在也沒用,因爲PHP不知道要讀 取哪個Session文件。我們知道PHP的Cookie過期時間是在創建時設置的,那麼PHP在創建session的同時爲客戶端創建的cookie的 生週期是多久?這個在php.ini中有設置:session.cookie_lifetime 。這個值默認是0,代表瀏覽器一關閉SESSIONID 就失效。那就是說我們把session.gc_maxlifetime和session.cookie_lifetime設置成同一個值就可以控制 Session的失效時間了

四:Session操作

    例如:新添加一個值$_SESSION['name'] ='xiaoming'; 那麼這個SESSION

_SESSION的值寫入到session_id指定的文件夾中。這個階段有 可能執行更改session_id的操作,可能銷燬一箇舊的的session_id,生成一個全新的session_id,例如:角色的轉換,當它登錄後 需要換用新的session_id

1 if (isset($_COOKIE[session_name()])) {2        setcookie(session_name(),'',time() -40000,'/');  // session cookie過期3  }4 session_regenerate_id();  //這一步會生成新的session_id,再調用session_id()返回的是新的值

銷燬session的方法有2種

第一種是通過程序session_destory()方法清除所有session   unset(session['x'])來清除指定的session['x']。

第二種是通過關閉瀏覽器,關閉後會直接清除所有session。

設置session生命週期的也有2種方法。

第一種  setcookie() 直接用setcookie設置session id的生命週期。

1 $lifetime=60;//保存1分鐘2 session_start();3 setcookie(session_name(),session_id(),time()+$lifetime,"/");

 第 二種  session_set_cookie_params()   其中session_regenerate_id();方法用於改變當前session_id的值,並保留session中數組的值。參數默認爲 false,如果設置爲true則改變session_id的值,並清空當前session數組。

1 $lifetime=60;//保存1分鐘2 session_set_cookie_params($lifetime);3 session_start();4 session_regenerate_id(true);

session相關概念

1) session id

    用戶session唯一標識符,隨機生成的一串字符串,具有唯一性,隨機性。主要用於區分其它用戶的session數據。用戶第一次訪問web頁面的時 候,php的session初始化函數調用會分配給當前來訪用戶一個唯一的ID,也稱之爲session_id。

2) session data

   我們把需要通過session保存的用戶狀態信息,稱爲用戶session數據,也稱爲session數據。

3) session file

   PHP默認將session數據存放在一個文件裏。我們把存放session數據的文件稱爲session文件。它由特殊的php.ini設置 session.save_path指定session文件的存放路徑,CentOS5.3操作系統,PHP5.1默認存放在/var/lib/php /session目錄中。

4) session lifetime

     我們把初始化session開始,直到註銷session這段期間,稱爲session生命週期,這樣有助於我們理解session管理函數。

與session存儲相關php.ini設置

1) session.save_handler = file

  用於讀取/回寫session數據的方式,默認是files。它會讓PHP的session管理函數使用指定的文本文件存儲session數據。

2) session.save_path =“/var/lib/php/session”

   指定保存session文件的目錄,可以指定到別的目錄,但是指定目錄必須要有httpd守護進程屬主(比如apache或www等)寫權限,否則無法 回存session數據。當指定目錄不存在時,php session環境初始化函數是不會幫你創建指定目錄的,所以需要你手工建立指定目錄。

它還可以寫成這樣session.save_path =“N;/path” 其中N是整數。這樣使得不是所有的session文件都保存在同一個目錄中,而是分散在不同目錄。這對於服務器處理大量session文件是很有幫助的。(注:目錄需要自己手工創建)

3) session.auto_start = 0

  如果啓用該選項,用戶的每次請求都會初始化session。我們推薦不啓用該設置,最好通過session_start()顯示地初始化session。

五:Session的同步與對影響系統性能

  1:session在大訪問量網站上確實影響系統性能,影響性能的原因之一由文件系統設計造成,在同一個目錄下超過10000個文件時,文件的 定位將非常耗時,PHP支持Session目錄hash,我們可以通過修改php.ini中session.save_path = “2;/path/to/session/dir”,那麼session將存儲在兩級子目錄中,每個目錄有16個子目錄[0~f],PHP session不支持創建目錄,需要事先把那麼些目錄創建好 。       

     2:小文件的效率問題,一般我們的Session數據都不會太大(1~2K),如果有大量這樣1~2K的文件在磁盤上,IO效率很差,PHP手冊上建議使用Reiserfs文件系統。   

六:同步問題(session共享)

       1:使用數據庫保存session, 使用數據庫來保存session,就算服務器宕機了也沒事,session照樣在。問題:程序需要定製;每次請求都進行數據庫讀寫開銷不小(使用內存數據 庫可以提高性能,宕機就會丟失數據。可供選擇的內存數據庫有BerkeleyDB,Mysql的內存表);另外數據庫是一個單點,可以做數據庫的ha來解 決這個問題。       

  2:使用 memcached來保存session, 這種方式跟數據庫類似,不過因爲是內存存取的,性能自然要比數據庫好多了。當然存儲在redis也是比較理想 的選擇,方便存儲統計在線人數,那麼存儲在redis中也實現了這個要求,而且redis支持的數據類型多。問題:程序需要定製,增加 了工作量;存入memcached中的數據都需要序列化,效率較低;如果是文件形式的,你可以用NFS統一存儲。

       3:還有一種方式是通過加密的cookie來實現,用戶在A服務器上登錄成功,在用戶的瀏覽器上添加一個加密的cookie,當用戶訪問B服務器時,檢查 有無Session,如果有當然沒問題,如果沒有,就去檢驗Cookie是否有效,Cookie有效的話就在B服務器上重建session。簡單,高效, 服務器的壓力減小了,因爲session數據不存在服務器磁盤上。根本就不會出現session讀取不到的問題。。 問題:網絡請求佔用很多。每次請求時,客戶端都要通過cookie發送session數據給服務器,session中數據不能太多,瀏覽器對cookie 的大小存在限制。每個瀏覽器限制是不同的,比如:Firefox 和Safari允許cookie 4097個字節,Opera允許cookie4096個字節,IE允許cookie4095個字節,所以不適合高訪問量的情況,因爲高訪問量的情況下,每 次請求瀏覽器都要發送session數據給服務器,一個cookie大小2k左右。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章