Session存在的意義,估計每個用做web開發的人都是了解的,就為了解決HTTP是個無狀態協議所帶來的問題,不多說了。這裡主要想說的是服務端與客戶端是如何利用session進行交互的。
先看下面這幅流程圖:
當用戶第一次訪問站點時,PHP會用session_start()函數為用戶創建一個session ID,這就是針對這個用戶的唯一標識,每一個訪問的用戶都會得到一個自己獨有的session ID,這個session ID會存放在響應頭裡的cookie中,之後發送給客戶端。這樣客戶端就會擁有一個該站點給他的session ID。
當用戶第二次訪問該站點時,浏覽器會帶著本地存放的cookie(裡面存有上次得到的session ID)隨著請求一起發送到服務器,服務端接到請求後會檢測是否有session ID,如果有就會找到響應的session文件,把其中的信息讀取出來;如果沒有就跟第一次一樣再創建個新的。
通常站點的退出功能,實際上就是調用一下session_destroy()函數(也有可能更復雜些),把該用戶的session文件刪除,再把用戶的cookie清除。這樣客戶端和服務端就算沒有聯系了。
圖中的紅框部分就是一次完整的HTTP請求,因為HTTP是無狀態的,所以一次請求完成後客戶端和服務端就不再有任何關系了,誰也不認識誰。但由於一些需要(如保持登錄狀態等),必須讓服務端和客戶端保持聯系,session ID就成了這種聯系的媒介了。
通過上面的分析我們可以知道session實際上是依賴與cookie的,當用戶訪問某一站點時,浏覽器會根據用戶訪問的站點自動搜索可用的cookie,如果有可用的就隨著請求一起發送到了服務端。每次接收到服務端的響應時又會更新本地的cookie信息。
當然也可以用GET方式來傳遞session ID,但不推薦用GET,這樣不安全。
由上面的流程圖可以看到,服務端實際上是把產生的一些數據存放在了session文件中,該文件的名字就是”sess“加上session ID,這些文件的存放位置就是phpinfo()查到的session.savepath值。
由上圖我們可以很清楚的看到,服務端和客戶端保存著同樣的session ID信息,這就是兩者保持聯系的鑰匙。
有好處必然也有壞處,session帶來的最主要問題就是對性能的影響,可以想象一下,對於一個千萬用戶級的web站點,如果每個用戶都保存 session文件,那每次用戶訪問光尋找相應的session文件就要耗掉不少系統資源的。所以這時就要對session的存儲做一些自定義的設定了, 如分目錄或哈希等等。除了保存到session文件,也可以拋棄PHP自帶的session功能,自己實現session,將session信息存放到數 據庫當中,這樣做最好對數據庫進行一下緩存的設置了,不然對上千萬的數據進行太頻繁的檢索,也是蠻耗資源的。
客戶端和服務端的這種聯系必然是需要有時間的規定的,所以需要定期清除session。這個問題就需要在兩方面考慮了,一個是清除服務端session文件,一個是清除客戶端的cookie信息,因為兩者都各保存著一半的信息。
PHP GC進程可以掃描session存放目錄清除session文件,但這個進程是特別耗資源的,所以PHP默認是1%的幾率在一個sessioin啟動時去 清理一次過期的sesssion,所以並不是說一個用戶session過期了,他對應的session文件就馬上被清除,99%的幾率是沒被清除的。這就 需要我們程序員自己動手了。可以在session信息中存放一個過期時間,值為用戶最後一次訪問的時間。當用戶一訪問,就用當前時間減去上次訪問時間看是 否超時,如果超時了就刪除相應session文件,並設置cookie的Expires屬性為負值,使其客戶端的cookie信息也過期,這樣浏覽器就自 動把它刪掉了。