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


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

 

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

    在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()

    功能:

      初始化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(); 
            ?> 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM