php 會話控制(關於session的維護與生命週期)

Session是由應用服務器維持的一個服務器端的存儲空間,用戶在鏈接服務器時,會由服務器建立生成一個惟一的sessionID,用該sessionID爲標識符存取服務器端的Session存儲空間,在會話期間,分配給客戶端的惟一sessionID,用來標識當前用戶,與其餘用戶進行區分。php

 

    sessionID也能夠做爲會話信息保存到數據庫中,進行session持久化。這樣能夠跟蹤用戶的登錄次數、在線與否在線時間等從而維護HTTP無狀態事物之間的關係。session的內容存儲鍵值對的列表,鍵是字符串類型,session的存儲更方便,值能夠是對象。web

    在session會話期間,session會分別保存在客戶端和服務器端兩個文件,客戶端能夠是cookie方式保存的sessionID(默認的保存方式)或經過url字符串形式傳遞。服務器端通常以文本的形式保存在指定的session目錄中。在服務器端session.use_cookies來控制客戶端使用哪種保存方式。數據庫

 

    若是定義爲cookie保存方式,咱們能夠經過session.cookie_lifetime(默認值0,閉瀏覽器就清除)來控制被保存在client上的cookie的有效期數組

 

    而若是客戶端用cookie方式保存的sessionID,則使用「臨時」的cookie保存(cookie的名稱爲PHPSESSID,經過Firebug你能夠了解到詳細的信息,該名稱你能夠經過php.ini session.name進行更改),用戶提交頁面時,會將這一SessionID提交到服務器端,來存取session數據。這一過程,是不用開發人員干預的瀏覽器

 

Session的建立服務器

    session_start()cookie

    功能:session

      初始化Session,也標識着session生命週期的開始。要使用session,必須初始化一個session環境,有點相似於OOP概念中調用構造函數構建立對象實例同樣。session初始化操做,聲明一個全局數組$_SESSION,映射寄存在內存的session數據。若是session文件已經存在,而且保存有session數據,session_start()則會讀取session數據,填入$_SESSION中,開始一個新的session生命週期。併發

    說明:函數

      若是在php.ini中session.auto_start=1開啓,則在每一個頁面執行session_start(),不須要手工設置,該選項默認爲關閉狀態,開啓後不能將對象放入session中。

    Session ID

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

    得到session_id():

      echo $_COOKIE['PHPSESSID'].'<br/>';
      echo $_COOKIE[session_name()].'<br/>';
      echo session_id().'<br/>';

 

備註

    php默認的session是基於cookie的,若是要刪除cookie的話,必須藉助setcookie()函數

    session_unset()和unset()函數區別:

      在session生命週期,session_unset()從當前session中註銷所有session數據,讓$_SESSION成爲一個空數組。它與unset($_SESSION)的區別在於:unset直接刪除$_SESSION變量,釋放內存資源;另外一個區別在於,session_unset()僅在session生命週期可以操做$_SESSION數組,而unset()則在整個頁面(page)生命週期都能操做$_SESSION數組。session_unset()一樣不進行任何IO操做,隻影響$_SESSION數組。

 

Session生命週期(session lifetime):Session失效時間與過時回收機制

    咱們把初始化session開始,直到註銷session這段期間,稱爲session生命週期。默認的,php會將session保存在php.ini配置中session.save_path設定的目錄下

    設置SESSION的生命週期

      php session是基於cookie的,因此要設置session的生命週期,首先要設置cookie的失效時間。由於在客戶端(如瀏覽器)登陸網站時,SESSION 是否有用,首先找客戶端是否有 COOKIE,經過COOKIE 中的 SESSION ID 去找服務器上的文件

    其實PHP5 Session還提供了一個函數 session_set_cookie_params(); 來設置PHP5 Session的生存期的,該函數必須在 session_start() 函數調用以前調用

    在服務器端,php如何判斷session文件是否過時?

      session.gc_maxlifetime = 1440 (初始值)#設置session存活時間,單位是秒。每次GC啓動後, 會經過stat獲得session文件最後訪問的unix時間,經過如今時間減去文件最後訪問時間之間大於session.gc_maxlifetime,則會刪除該文件。

      若是"最後的修改時間"到"如今"超過了session.gc_maxlifetime(默認是1440)秒,也就是說在這裏設置的時間內,該文件沒有被修改過,這個session文件就被認爲是過時了,因爲php5的session採用被動的回收機制,過時的session文件不會本身消失,而是經過觸發「回收」來處理過時的session,那麼在下一次session回收的時候,若是這個文件仍然沒有被更改過,這個session文件就會被刪除(session就過時了)。

    session回收什麼時候發生

      默認狀況下,每一次php請求,就會有1%的機率發生回收,因此可能簡單的理解爲「每100次php請求就可能有一次回收機率發生」。這個機率是經過如下參數控制的:

        session.gc_probability = 1 (初始值)
        session.gc_divisor = 100 (初始值)

        #由這二個函數決定了啓用GC的機率,默認是1/1000。也就是說,每一千次用戶請求中有一次會啓動GC回收session。啓動GC進程不宜過於頻繁。過於頻繁訪問的網站,併發量大的網站,可減少PHP GC的啓動頻率。PHP GC回收session會下降php的執行效率。

      這兩個合起來就是啓動Gabadge Collection(gc)進程管理機率的,在session初使化時(session_start())。Gabadge Collection啓動後跟蹤session信息文件。其啓動機率爲session.gc_probability/session.gc_divisor。也就是說不是每一個session信息文件都有100%的被系統看成垃圾來處理的。若是直接關閉瀏覽器的話,session信息文件不少狀況下都是留在了服務器上,若是把機率改爲了100%,雖然Gabadge Collection百分之百被啓動了,可是這會對服務器添加負荷,也就失去了GC自己的意義了。

      補充說明

        假設這種狀況session.gc_maxlifetime=1440,若是某個session文件最後修改時間是1440秒以前,那麼在下一次回收(1/100的機率)發生前,這個session仍然是有效的;

        若是你的session使用session.save_path中使用別的地方保存session,session回收機制有可能不會自動處理過時session文件。這時須要定時手動(或者crontab)的刪除過時的session:cd /path/to/sessions; find -cmin +24 | xargs rm;

        注意,當服務器端session文件數量沒有獲得有效的回收,逐漸增加到GB或更大級別時可能你的站點在存取session時就會愈來愈緩慢,多見於站點登入登出會受到影響;

        寫日誌、週報、月報等時候咱們最後提交的關頭,有時會出現」無效的操做,請登錄後重試」等消息,其緣由也不言而喻,可能就是session失效,gc清除那些已經「超時」的session文件。

        一些特殊狀況:

          由於回收機制會檢查文件的「最後修改時間」,因此若是某個會話是活躍的,可是session的內容沒有改變過,那麼對應的session文件也就沒有改變過,回收機制會認爲這是一個長時間沒有活躍的session而將其刪除。這是咱們不肯看到的,能夠經過增長以下的簡單代碼解決這個問題:

            <?php              if(!isset($_SESSION['last_access'])||(time()-$_SESSION['last_access'])>120)                  $_SESSION['last_access'] = time();             ?> 

相關文章
相關標籤/搜索