php會話機制參考:我的隨筆
緣起
網站,通常會有多個服務器,多個子域名,每個節點運行着不同模塊。有時為了整體體驗,用戶用同一個用戶名、密碼瀏覽整站,不用重復登錄。這時候就需要多服務器共享session_id和session數據,即生成的session_id是一樣的,且能共同訪問相同的session數據。
session簡單原理
瀏覽器客戶端登錄網站時,PHP使用 session_start() 打開 SESSION,這樣就會產生客戶端的SESSION ID(此 ID 可通過函數 session_id() 獲取/設置)。服務器返回set_cookie,瀏覽器將session_id保存進入cookie。默認COOKIE 的名為 PHPSESSID,可在php.ini設置。
默認情況下,php.ini 中設置的 SESSION 保存方式是 files(session.save_handler = files),目錄由 session.save_path 指定,文件名以 sess_ SESSION ID,如:sess_c72665af28xxooffggggb51b。如果訪問量大, SESSION 文件多的話,可以設置分級目錄保存:session.save_path="N;/save_path",N 為分級的級數,save_path 為開始目錄。
多服務器共享
了解 SESSION 的工作原理,發現,默認各個服務器會對同一個客戶端產生 不同的SESSION ID,如同一個用戶瀏覽器,A 服務器產生的是 30fhrde1e9de31tggne2992dddb6h0a,而 B 服務器生成的則是 c23fghjkloip014c0fergggggg000w8e1b。
要達到共享,就需要生成的會話id一致,並且會話數據能被所有服務器訪問到。
默認情況下,COOKIE 的域是當前服務器的域名/IP 地址,而域不同的話,各個服務器所設置的 COOKIE 是不能相互訪問的。可以設置 COOKIE 的域為 .xxoo.com,這樣 a.xxoo.com、b.xxoo.com 等等都可以產生並訪問相同的COOKIE,在通過cookie獲取會話信息了。PHP 代碼中的設置方法如下
至於session數據的存放,因為在多服務器下需要都能訪問,所以可以存在數據庫,redis/memcache等大家都能讀取到的地方。
默認情況下 SESSION 數據是以文件方式保存,想要使用其他方式保存,就必須重新自定義 SESSION 各個操作的處理函數。PHP 提供了session_set_save_handle() 函數,可以用此函數自定義 SESSION 的處理方式。
//不使用 GET/POST 變量方式傳遞
ini_set('session.use_trans_sid', 0);//設置垃圾回收時間
ini_set('session.gc_maxlifetime', 3600);//使用 COOKIE 保存 SESSION ID 的方式
ini_set('session.use_cookies', 1);
ini_set('session.cookie_path', '/');//設置多域名
ini_set('session.cookie_domain', '.xxoo.com');//將 session.save_handler 設置為 user自定義,而不是默認的 files
session_module_name('user');//定義 SESSION操作所對應的方法名:
session_set_save_handler(
array('OP_class', 'open'), //對應於靜態方法 My_Sess::open(),下同。
array('OP_class', 'close'),
array('OP_class', 'read'),
array('OP_class', 'write'),
array('OP_class', 'destroy'),
array('OP_class', 'gc')
);
關鍵函數:session_set_save_handler ( string open, string close, string read, string write, string destroy, string gc ) 參考文檔說明。