PHP實(shí)現(xiàn)多服務(wù)器共享SESSION數(shù)據(jù)_第1頁
PHP實(shí)現(xiàn)多服務(wù)器共享SESSION數(shù)據(jù)_第2頁
PHP實(shí)現(xiàn)多服務(wù)器共享SESSION數(shù)據(jù)_第3頁
PHP實(shí)現(xiàn)多服務(wù)器共享SESSION數(shù)據(jù)_第4頁
PHP實(shí)現(xiàn)多服務(wù)器共享SESSION數(shù)據(jù)_第5頁
免費(fèi)預(yù)覽已結(jié)束,剩余1頁可下載查看

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、、問題起源 稍大一些的網(wǎng)站,通常都會(huì)有好幾個(gè)服務(wù)器, 每個(gè)服務(wù)器運(yùn)行著不同功能的模塊, 使用不同的二級(jí)域名, 而一個(gè)整體性強(qiáng)的網(wǎng)站, 用戶系統(tǒng)是統(tǒng)一的, 即一套用戶 名、密碼在整個(gè)網(wǎng)站的各個(gè)模塊中都是可以登錄使用的。 各個(gè)服務(wù)器共享用戶數(shù) 據(jù)是比較容易實(shí)現(xiàn)的, 只需要在后端放個(gè)數(shù)據(jù)庫服務(wù)器, 各個(gè)服務(wù)器通過統(tǒng)一接 口對(duì)用戶數(shù)據(jù)進(jìn)行訪問即可。 但還存在一個(gè)問題, 就是用戶在這個(gè)服務(wù)器登錄之 后,進(jìn)入另一個(gè)服務(wù)器的別的模塊時(shí),仍然需要重新登錄,這就是一次登錄,全 部通行的問題, 映射到技術(shù)上, 其實(shí)就是各個(gè)服務(wù)器之間如何實(shí)現(xiàn)共享 SESSION 數(shù)據(jù)的問題。、PHP SESSION勺工作原理在解決

2、問題之前,先來了解一下 PHP SESSIO N的工作原理。在客戶端(如瀏覽 器)登錄網(wǎng)站時(shí),被訪問勺 PHP 頁面可以使用 session_start() 打開 SESSION, 這樣就會(huì)產(chǎn)生客戶端的唯一標(biāo)識(shí) SESSIOND (此ID 可通過函數(shù)session_id() 獲取/ 設(shè)置)。 SESSIONID 可以通過兩種方式保留在客戶端,使得請(qǐng)求不同的頁 面時(shí),PHP程序可以獲知客戶端的 SESSION ID; 種是將SESSION ID自動(dòng)加 入到 GET 的 URL 中,或者 POST 的表單中,默認(rèn)情況下,變量名為 PHPSESSID; 另一種是通過COOKIE將SESSION ID

3、保存在COOKIE中,默認(rèn)情況下,這個(gè) COOKIE的名字為PHPSESSID這里我們主要以COOKIE方式進(jìn)行說明,因?yàn)閼?yīng) 用比較廣泛。那么 SESSION 的數(shù)據(jù)保存在哪里呢?當(dāng)然是在服務(wù)器端, 但不是保存在內(nèi)存中, 而是保存在文件或數(shù)據(jù)庫中。默認(rèn)情況下, php.ini 中設(shè)置的 SESSION 保存方 式是 files ( session.save_handler = files ),即使用讀寫文件的方式保存 SESSION數(shù)據(jù),而SESSION文件保存的目錄由session.save_path指定,文件名以sess_ 為前綴,后跟SESSION ID,如: sess_c72665af

4、28a8b14c0fe11afe3b59b51b 。文件中的數(shù)據(jù)即是序列化之后的 SESSION數(shù)據(jù)了。如果訪問量大,可能產(chǎn)生的 SESSION文件會(huì)比較多,這時(shí)可 以設(shè)置分級(jí)目錄進(jìn)行 SESSION 文件的保存,效率會(huì)提高很多,設(shè)置方法為: session.save_path="N;/save_path" , N 為分級(jí)的級(jí)數(shù), save_path 為開始目錄。 當(dāng)寫入SESSION數(shù)據(jù)的時(shí)候,PHP會(huì)獲取到客戶端的SESSION_ID然后根據(jù)這 個(gè) SESSION ID 到指定的 SESSION 文件保存目錄中找到相應(yīng)的 SESSION 文件, 不存在則創(chuàng)建之,最后將數(shù)

5、據(jù)序列化之后寫入文件。讀取SESSION 數(shù)據(jù)是也是類似的操作流程,對(duì)讀出來的數(shù)據(jù)需要進(jìn)行解序列化,生成相應(yīng)的 SESSION 變 量。三、多服務(wù)器共享 SESSION 的主要障礙及解決辦法通過了解SESSION的工作原理,我們可以發(fā)現(xiàn),在默認(rèn)情況下,各個(gè)服務(wù)器會(huì)各自分別對(duì)同一個(gè)客戶端產(chǎn)生 SESSION ID,如對(duì)于同一個(gè)用戶瀏覽器,A服務(wù)器產(chǎn)生的 SESSIOND 是 30de1e9de3192ba6ce2992d27a1b6a0a 而 B 服務(wù)器生 成的則是 C72665af28a8b14c0fe11afe3b59b51b。另外,PHP的 SESSION 數(shù)據(jù)都 是分別保存在本服務(wù)器的文

6、件系統(tǒng)中。如下圖所示:多服務(wù)器對(duì)同一客戶端分別設(shè)畳各自的COOKIE,并分別在備自的文件系統(tǒng)中保存SESSION數(shù)據(jù)文件確定了問題所在之后,就可以著手進(jìn)行解決了。想要共享SESSION數(shù)據(jù),那就必須實(shí)現(xiàn)兩個(gè)目標(biāo):一個(gè)是各個(gè)服務(wù)器對(duì)同一個(gè)客戶端產(chǎn)生的SESSIONID必須相同,并且可通過同一個(gè)COOKIE進(jìn)行傳遞,也就是說各個(gè)服務(wù)器必須可以讀取 同一個(gè)名為PHPSESSID的 COOKIE另一個(gè)是SESSION數(shù)據(jù)的存儲(chǔ)方式/位置必 須保證各個(gè)服務(wù)器都能夠訪問到。簡(jiǎn)單地說就是多服務(wù)器共享客戶端的 SESSION ID,同時(shí)還必須共享服務(wù)器端的 SESSION數(shù)據(jù)。第一個(gè)目標(biāo)的實(shí)現(xiàn)其實(shí)很簡(jiǎn)單,只需

7、要對(duì)COOKIE的域(domain)進(jìn)行特殊地設(shè) 置即可,默認(rèn)情況下,COOKIE的域是當(dāng)前服務(wù)器的域名/IP地址,而域不同的 話,各個(gè)服務(wù)器所設(shè)置的 COOKIE是不能相互訪問的,如 的服務(wù) 器是不能讀寫 服務(wù)器設(shè)置的COOKIE的。這里我們所說的同一網(wǎng) 站的服務(wù)器有其特殊性,那就是他們同屬于同一個(gè)一級(jí)域,女口: 和都屬于域 ,那么我們就可以設(shè)置COOKIE的 域?yàn)?,這樣 、 等等都可以訪 問此COOKIE PHP代碼中的設(shè)置方法如下:v?phpini_set ('session.cookie_domain', '');?>這樣各個(gè)服務(wù)器共享同一客戶端

8、 SESSION ID的目的就達(dá)到了。第二個(gè)目標(biāo)的實(shí)現(xiàn)可以使用文件共享方式,如NFS方式,但設(shè)置、操作上有些復(fù)雜。我們可以參考先前所說的統(tǒng)一用戶系統(tǒng)的方式,即使用數(shù)據(jù)庫來保存 SESSION數(shù)據(jù),這樣各個(gè)服務(wù)器就可以方便地訪問同一個(gè)數(shù)據(jù)源,獲取相同的 SESSION數(shù) 據(jù)了。解決辦法如下圖所示:DATABASE多服務(wù)器對(duì)同一客戶端共享同一 COOKIE,幷在服務(wù)第端邇過數(shù)藉庫共亨SESSION數(shù)據(jù)四、代碼實(shí)現(xiàn)首先創(chuàng)建數(shù)據(jù)表,MySQL的SQL語句如下:CREATE TABLE 'sess' ('sesskey' varchar(32) NOT NULL defa

9、ult ”,'expiry' big in t(20) NOT NULL default '0','data' lo ngtext NOT NULL,PRIMARY KEY ('sesskey'),KEY 'expiry' ('expiry')TYPE=MylSAMsesskey 為 SESSION ID,expiry 為 SESSION 過期時(shí)間,data 用于保存 SESSION數(shù) 據(jù)。默認(rèn)情況下SESSION數(shù)據(jù)是以文件方式保存,想要使用數(shù)據(jù)庫方式保存,就必 須重新定義SESSION各個(gè)操作的

10、處理函數(shù)。PHP提供了session setsavehandle()函數(shù),可以用此函數(shù)自定義 SESSION的處理過程,當(dāng)然首先要先將session.save_handler改成user,可在PHP中進(jìn)行設(shè)置:v?phpsession_module_name('user'); ?>接下來著重講一下 session_set_save_handle() 函數(shù),此函數(shù)有六個(gè)參數(shù): session_set_save_handler ( string open, string close, string read, string write, string destroy, str

11、ing gc )各個(gè)參數(shù)為各項(xiàng)操作的函數(shù)名,這些操作依次是:打開、關(guān)閉、讀取、寫入、銷 毀、垃圾回收。 PHP 手冊(cè)中有詳細(xì)的例子, 在這里我們使用 OO 的方式來實(shí)現(xiàn)這 些操作,詳細(xì)代碼如下:<?phpdefine ( 'MY_SESS_TIME, ' 3600);/SESSION 生存時(shí)長(zhǎng)/ 類定義class My_Sessfunction init ()$domain = '' ;/不使用GET/POST變量方式ini_set ( 'session.use_trans_sid' , 0);/ 設(shè)置垃圾回收最大生存時(shí)間ini_set (

12、 'session.gc_maxlifetime' , MY_SESS_TIM);E / 使用 COOKIE 保存 SESSION ID 的方式ini_set( 'session.use_cookies' ,1);ini_set( 'session.cookie_path' ,'/' );/ 多主機(jī)共享保存 SESSION ID 的 COOKIE ini_set( 'session.cookie_domain',$domain);/ 將 session.save_handler 設(shè)置為 user ,而不是默認(rèn)的 f

13、iles session_module_name( 'user' );/定義SESSION各項(xiàng)操作所對(duì)應(yīng)的方法名:array(Sess:'My_Sess' , open() ,下同。'open'),array( 'My_Sess' ,'close'),array('My_Sess' ,'read'),array('My_Sess' ,'write'),array('My_Sess' ,'destroy' ),array(

14、'My_Sess' ,'gc' )session_set_save_handler (/ 對(duì)應(yīng)于靜態(tài)方); /end functionfunction open( $save_path , $session_name) return true ;/end functionfunction close () global $MY_SESS_CO;NNif ($MY_SESS_CO)N N/ 關(guān)閉數(shù)據(jù)庫連接$MY_SESS_CO->NNClose(); return true ; /end functionfunction read ( $sesskey )

15、global $MY_SESS_CO;NN$sql = 'SELECT data FROM sess WHERE sesskey=' . $MY_SESS_CONN -> qstr ( $sesskey) . ' AND expiry>=' . time ();$rs =& $MY_SESS_CO->NENxecute ( $sql ); if ($rs) if ($rs -> EOF) return/ 讀取到對(duì)應(yīng)于 SESSION ID 的 SESSION 數(shù)據(jù) $v = $rs -> fields 0;$rs ->

16、 Close();$v;return/end if /end if return " /end functionfunction write ( $sesskey , $data ) global $MY_SESS_CO;NN$qkey = $MY_SESS_CO->NqNstr ( $sesskey);$expiry = time () + My_SESS_TIM; E / 設(shè)置過期時(shí)間/ 寫入 SESSION$arr = array('sesskey' => $qkey,'expiry'=> $expiry ,'data&

17、#39;=> $data );$MY_SESS_CO->NRNeplace( 'sess' , $arr , 'sesskey' , $autoQuote =true );return true ; /end functionfunction destroy ( $sesskey ) global $MY_SESS_CO;NN$sql = 'DELETE FROM sess WHERE sesskey='. $MY_SESS_CO->NqNst r ( $sesskey);$rs =& $MY_SESS_CO->N

18、ENxecute ( $sql ); return true ;/end functionfunction gc( $maxlifetime = null ) global $MY_SESS_CO;NN$sql = 'DELETE FROM sess WHERE expiry<' . time (); $MY_SESS_CO->NENxecute ( $sql );/ 由于經(jīng)常性的對(duì)表 sess 做刪除操作,容易產(chǎn)生碎片, / 所以在垃圾回收中對(duì)該表進(jìn)行優(yōu)化操作。$sql = 'OPTIMIZE TABLE sess' ; $MY_SESS_CO->NENxecute ( $sql );return true ; /end function /: / 使用 ADOdb 作為數(shù)據(jù)庫抽象層。 require_once( 'adodb/adodb.inc.php' );/ 數(shù)據(jù)庫配置項(xiàng),可放入配置文件中(如: config.in

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論