ホームページ  >  記事  >  バックエンド開発  >  PHP は SESSION データを共有するために複数の Web サーバーを実装します_PHP チュートリアル

PHP は SESSION データを共有するために複数の Web サーバーを実装します_PHP チュートリアル

WBOY
WBOYオリジナル
2016-07-15 13:23:371016ブラウズ

1. 問題の原因 やや大規模な Web サイトでは通常、複数のサーバーが異なる機能を備えたモジュールを実行し、異なる第 2 レベルのドメイン名を使用します。ユーザー名とパスワードのセットを使用して、Web サイト全体のすべてのモジュールにログインできます。各サーバーがユーザー データを共有するのは比較的簡単で、バックエンドにデータベース サーバーを配置するだけで済み、各サーバーは統一されたインターフェイスを通じてユーザー データにアクセスできます。しかし、まだ問題があります。つまり、ユーザーがこのサーバーにログインした後、別のサーバーの他のモジュールに入るときに、再度ログインする必要があります。これは 1 回限りのログインであり、一般的な問題はすべて にマッピングされています。実際には、さまざまなサーバー間で SESSION データを共有する方法です。
2. PHP SESSION の動作原理
問題を解決する前に、まず PHP SESSION の動作原理を理解しましょう。クライアント (ブラウザなど) が Web サイトにログインすると、訪問した PHP ページは session_start() を使用して SESSION を開くことができ、これによりクライアントの一意の識別 SESSION ID が生成されます (この ID は関数 session_id( ))。 SESSION ID は 2 つの方法でクライアントに保持できるため、PHP プログラムは別のページをリクエストするときにクライアントの SESSION ID を学習できます。1 つは、デフォルトで GET URL または POST フォームに SESSION ID を自動的に追加することです。最初の方法では、変数名は PHPSESSID ですが、もう 1 つの方法では、COOKIE を通じてセッション ID を保存します。デフォルトでは、この COOKIE の名前は PHPSESSID です。ここでは、広く使われている COOKIE メソッドを中心に説明します。
それでは、SESSION データはどこに保存されるのでしょうか?もちろんサーバー側では、メモリに保存されるのではなく、ファイルまたはデータベースに保存されます。デフォルトでは、php.ini で設定される SESSION の保存方法はファイル (session.save_handler = files) です。つまり、ファイルの読み書きによって SESSION データが保存され、SESSION ファイルが保存されるディレクトリはセッションによって指定されます。 save_path であり、sess_c72665af28a8b14c0fe11afe3b59b51b のように、ファイル名は接頭辞である sess_ で始まり、その後にセッション ID が続きます。ファイル内のデータはシリアル化後の SESSION データです。アクセス数が多い場合は、さらに多くの SESSION ファイルが生成される可能性があります。この場合、SESSION ファイルを保存するための階層ディレクトリを設定すると、設定方法が大幅に向上します。 session.save_path= N;/save_path"、N は階層レベル、save_path は開始ディレクトリです。 SESSION データを書き込むとき、PHP はクライアントの SESSION_ID を取得し、この SESSION ID を使用して、指定された SESSION ファイル格納ディレクトリ内で対応する SESSION ファイルを検索し、存在しない場合は作成し、最後にデータをシリアル化して書き込みます。ファイル。 。 SESSION データの読み取りも同様の操作プロセスで、読み取りデータを逆シリアル化する必要があり、対応する SESSION 変数が生成されます。
3. マルチサーバー共有 SESSION の主な障害と解決策 SESSION の動作原理を理解すると、デフォルトでは、各サーバーが同じクライアントに対して別々に SESSION ID を生成することがわかります。 client ユーザーのブラウザでは、サーバー A によって生成された SESSION ID は 30de1e9de3192ba6ce2992d27a1b6a0a ですが、サーバー B によって生成された SESSION ID は c72665af28a8b14c0fe11afe3b59b51b です。また、PHP の SESSION データは、このサーバーのファイル システムに別途保存されます。
問題を特定したら、解決を開始できます。 SESSION データを共有したい場合は、2 つの目標を達成する必要があります。1 つは、同じクライアントに対して各サーバーによって生成された SESSION ID が同じである必要があり、同じ COOKIE を介して渡せることです。つまり、各サーバーは次のことを行うことができなければなりません。 PHPSESSID という名前の同じ SESSION ID を読み取ります。
もう 1 つは、SESSION データの保存方法と場所が各サーバーにアクセスできるようにする必要があることです。 簡単に言えば、複数のサーバーはクライアントの SESSION ID を共有し、サーバーの SESSION データも共有する必要があります。
最初の目標の実現は、実際には、COOKIE のドメインを特別に設定するだけです。デフォルトでは、COOKIE のドメインは、現在のサーバーのドメイン名/IP アドレスになります。 、それぞれ サーバーによって設定された COOKIES は相互にアクセスできません。

4. コードの実装
まず、MySQL の SQL ステートメントは次のとおりです: CREATE TABLE `sess` ( `sesskey` varchar(32) NOT NULL default '', `expiry` bigint(20) NOT NULLデフォルト '0' 、`data` longtext NOT NULL、PRIMARY KEY (`sesskey`)、KEY `expiry` (`expiry`) ) TYPE=MyISAM sesskey は SESSION ID、expiry は SESSION 有効期限、データが使用されますSESSIONデータを保存します。
デフォルトでは、SESSION データはファイル モードで保存されます。データベース モードで保存したい場合は、各 SESSION オペレーションの処理関数を再定義する必要があります。PHP には session_set_save_handle() 関数が用意されており、この関数を使用して SESSION 処理プロセスをカスタマイズすることができます。これは、PHP で設定できる session_module_name('user'); です。焦点は次のとおりです。 session_set_save_handle() 関数を見てみましょう。
この関数には 6 つのパラメータがあります: session_set_save_handler (string open、string close、
string read、string write、string destroy、string gc) 各パラメータはそれぞれの関数名です。これらの操作は順番に行われます:
オープン、クローズ、読み取り、書き込み、破棄、ガベージ コレクション。詳細な例は PHP マニュアルにあります。
ここでは OO を使用してこれらの操作を実装します。詳細なコードは次のとおりです。

<br><?php define ( 'MY_SESS_TIME' , 3600 ); <br>//SESSION 生存时长 <br>//类定义 class My_Sess { function init () { $domain = '.infor96.com' ; <br>//不使用 GET/POST 变量方式 ini_set ( 'session.use_trans_sid' , 0 ); <br>//设置垃圾回收最大生存时间 ini_set ( 'session.gc_maxlifetime' , MY_SESS_TIME ); <br>//使用 COOKIE 保存 SESSION ID 的方式 ini_set ( 'session.use_cookies' , 1 ); <br>ini_set ( 'session.cookie_path' , '/' );<br>//多主机共享保存 SESSION ID 的 COOKIE ini_set ( 'session.cookie_domain' , $domain ); <br>//将 session.save_handler 设置为 user, <br>//而不是默认的 files session_module_name ( 'user' ); <br>//定义 SESSION 各项操作所对应的方法名: session_set_save_handler ( array( 'My_Sess' , 'open' ), <br>//对应于静态方法 My_Sess::open(),<br>下同。 <br>array( 'My_Sess' , 'close' ), array( 'My_Sess' , 'read' ),<br>array( 'My_Sess' , 'write' ), array( 'My_Sess' , 'destroy' ),<br>array( 'My_Sess' , 'gc' ) ); }<br>//end function function open ( $save_path , $session_name ) { return true ; } <br>//end function function close () { global $MY_SESS_CONN ; if ( $MY_SESS_CONN ) {<br>//关闭数据库连接 $MY_SESS_CONN -> Close (); } return true ; }<br>//end function function read ( $sesskey ) { global $MY_SESS_CONN ;<br>$sql = 'SELECT data FROM sess WHERE sesskey=' <br>. $MY_SESS_CONN -> qstr ( $sesskey ) . ' AND expiry>=' . time ();<br>$rs =& $MY_SESS_CONN -> Execute ( $sql ); <br>if ( $rs ) { if ( $rs -> EOF ) { return '' ; } else {<br>//读取到对应于 SESSION ID 的 SESSION 数据 $v = $rs -> fields [ 0 ]; $rs -> Close (); return $v ; } <br>//end if } <br>//end if return '' ; } <br>//end function function write ( $sesskey , $data ) { global $MY_SESS_CONN ; $qkey = $MY_SESS_CONN -> qstr ( $sesskey );<br>$expiry = time () + My_SESS_TIME ; <br>//设置过期时间<br>//写入 SESSION $arr = array( 'sesskey' => $qkey , 'expiry' => $expiry , 'data' => $data );<br>$MY_SESS_CONN -> Replace ( 'sess' , $arr , 'sesskey' , $autoQuote = true );<br>return true ; } <br>//end function function destroy ( $sesskey ) { global $MY_SESS_CONN ;<br>$sql = 'DELETE FROM sess WHERE sesskey=' . $MY_SESS_CONN -> qstr ( $sesskey );<br>$rs =& $MY_SESS_CONN -> Execute ( $sql ); return true ; }<br>//end function function gc ( $maxlifetime = null ) { global $MY_SESS_CONN ;<br>$sql = 'DELETE FROM sess WHERE expiry<' . time (); $MY_SESS_CONN -> Execute ( $sql );<br>//由于经常性的对表 sess 做删除操作,容易产生碎片,<br>//所以在垃圾回收中对该表进行优化操作。<br>$sql = 'OPTIMIZE TABLE sess' ;<br>$MY_SESS_CONN -> Execute ( $sql ); return true ; } <br>//end function } ///:~<br>//使用 ADOdb 作为数据库抽象层。 require_once( 'adodb/adodb.inc.php' );<br>//数据库配置项,可放入配置文件中(如:config.inc.php)。 $db_type = 'mysql' ;<br>$db_host = '192.168.212.1' ; <br>$db_user = 'sess_user' ; <br>$db_pass = 'sess_pass' ; $db_name = 'sess_db' ;<br>//创建数据库连接,这是一个全局变量。 $GLOBALS [ 'MY_SESS_CONN' ] =& ADONewConnection ( $db_type ); <br>$GLOBALS [ 'MY_SESS_CONN' ]-> Connect ( $db_host , $db_user , $db_pass , $db_name );<br>//初始化 SESSION 设置,必须在 session_start() 之前运行!! My_Sess :: init (); ?> <br>
5. 残りの問題 Web サイトのアクセス数が多い場合。 , SESSION データベースへの読み書きが頻繁に動作するため、効率が大幅に低下します。通常、SESSION データはそれほど大きくないことを考慮して、C/Java でマルチスレッド プログラムを作成し、HASH テーブルを使用して SESSION データを保存し、ソケット通信を通じてデータの読み書きを試みることができます。メモリに保存され、読み書き速度が大幅に向上するはずです。さらに、負荷分散によりサーバーの負荷を分散できます。 (担当編集者:

)

http://www.bkjia.com/PHPjc/446839.htmlwww.bkjia.com本当http://www.bkjia.com/PHPjc/446839.html技術記事 1. 問題の原因は、大規模な Web サイトには通常複数のサーバーがあり、各サーバーが異なる機能を持つモジュールを実行し、異なる第 2 レベルのドメイン名を使用し、包括的なネットワークを使用していることです...
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。