ホームページ  >  記事  >  バックエンド開発  >  PHP はマルチサーバー共有 SESSION データを尊重します

PHP はマルチサーバー共有 SESSION データを尊重します

WBOY
WBOYオリジナル
2016-06-13 13:25:27704ブラウズ

PHP は SESSION データのマルチサーバー共有を実装します

1. 問題の原因
通常、少し大きな Web サイトには複数のサーバーがあり、各サーバーは異なる機能を持つモジュールを実行し、異なるセカンダリ ドメイン名を使用します。統合 Web サイトでは、ユーザー システムが統合されています。つまり、一連の
ユーザー名とパスワードを使用して、Web サイト全体の各モジュールにログインできます。各サーバーがユーザー データを共有するのは比較的簡単で、バックエンドにデータベース サーバーを配置するだけで済み、各サーバーは統一されたインターフェイスを通じてユーザー データにアクセスできます。しかし、まだ問題があります。つまり、ユーザーがこのサーバーにログインした後、別のサーバーの他のモジュールに入るときに、再度ログインする必要があります。これは 1 回限りのログインであり、テクノロジーへのマッピングはすべて問題ありません。 、実際には、さまざまなサーバー間で SESSION データを共有する方法です。

2. PHP SESSION の動作原理
問題を解決する前に、まず PHP SESSION の動作原理を理解しましょう。クライアント (ブラウザなど) が Web サイトにログインすると、訪問した PHP ページは session_start() を使用して SESSION を開くことができます。これにより、クライアントの一意の ID SESSION ID が生成されます (この ID は関数を介して渡すことができます)
session_id() 取得/設定)。 SESSION ID は 2 つの方法でクライアントに保持できるため、別のページをリクエストするときに、PHP プログラムはクライアントの
SESSION ID を学習できます。1 つは、GET の URL またはフォームに SESSION ID を自動的に追加することです。 POST のデフォルトでは、変数名は
PHPSESSID です。もう 1 つは、COOKIE を通じてセッション ID を保存することです。デフォルトでは、この COOKIE の名前は
PHPSESSID です。ここでは、広く使われている COOKIE メソッドを中心に説明します。
それでは、SESSION データはどこに保存されるのでしょうか?もちろんサーバー側では、メモリに保存されるのではなく、ファイルまたはデータベースに保存されます。デフォルトでは、php.ini で設定される
SESSION 保存方法はファイル (session.save_handler = files) です。つまり、SESSION
データはファイルの読み取りと書き込みによって保存され、SESSION ファイルが保存されるディレクトリになります。 session.save_path によって設定されます。 sess_c72665af28a8b14c0fe11afe3b59b51b のように、ファイル名の前に sess_ を付け、その後に SESSION
ID を付けるように指定します。ファイル内のデータは、シリアル化後の SESSION
データです。アクセス数が多い場合、より多くの SESSION ファイルが生成される可能性があります。この場合、SESSION
ファイルを保存するための階層ディレクトリを設定すると、効率が大幅に向上します。 save_path="N;/save_path"、N は階層レベル、save_path
は開始ディレクトリです。 SESSION データを書き込むとき、PHP はクライアントの SESSION_ID を取得し、この SESSION ID を使用して、指定された
SESSION ファイル格納ディレクトリ内で対応する SESSION ファイルを検索し、存在しない場合は作成し、最後にデータをシリアル化します。ファイルに書き込みます。 SESSION
データの読み取りも同様の操作プロセスです。読み取りデータは逆シリアル化される必要があり、対応する SESSION 変数が生成されます。

3. マルチサーバー共有 SESSION の主な障害と解決策
SESSION の動作原理を理解すると、デフォルトで各サーバーが同じクライアントを共有することがわかります。 ID。たとえば、同じユーザー ブラウザの場合、サーバー A によって生成される SESSION ID は 30de1e9de3192ba6ce2992d27a1b6a0a ですが、サーバー B によって生成される SESSION ID は c72665af28a8b14c0fe11afe3b59b51b です。さらに、PHP の SESSION
データは、このサーバーのファイル システムに個別に保存されます。下の図に示すように:


問題を特定したら、解決を開始できます。 SESSION データを共有したい場合は、2 つの目標を達成する必要があります。1 つは、同じクライアントに対して各サーバーによって生成された
SESSION ID が同じである必要があり、同じ COOKIE を介して渡せることです。つまり、各サーバーは、読み取り可能であること。PHPSESSID という名前の同じ COOKIE を使用します。もう 1 つは、SESSION データの保存方法/場所が各サーバーにアクセスできるようにする必要があることです。 [color="green"]簡単に言うと、複数のサーバーはクライアントの SESSION ID を共有し、サーバーの SESSION データも共有する必要があります。
最初の目標の実現は、実際には非常に簡単です。デフォルトでは、COOKIE のドメインは現在のサーバーのドメイン名/IP アドレスです。たとえば、
?

www.aaa.com
のサーバーは相互にアクセスできません。読み取りまたは書き込み?
www.bbb.com
サーバーによって設定された COOKIE。ここで説明している同じ Web サイトのサーバーにはそれぞれ独自の特徴があります。つまり、aaa.infor96.com と ?
www .infor96.com はすべてドメイン .infor96.com に属しているため、COOKIE ドメインを .infor96.com に設定すると、aaa.infor96.com、www になります。 .infor96.com など。この COOKIE にアクセスできます。 PHP コードでの設定方法は以下のとおりです:
('session.cookie_domain', '.infor96.com');
?>
このように、各サーバーの目的は同じです。クライアントのセッション ID が取得されます。
2 番目の目標は、NFS などのファイル共有方法を使用して達成できますが、セットアップと操作はやや複雑です。前述のユーザー システムを統合する方法、つまりデータベースを使用して SESSION データを保存する方法を参照すると、各サーバーが同じデータ ソースに簡単にアクセスして同じ SESSION データを取得できます。
解決策は次の図のようになります。


4. コードの実装 まず、MySQL の SQL ステートメントを作成します。
? ?CREATE TABLE `sess` (
? ???`sesskey` varchar(32) NOT NULL デフォルト '',
? ?? ?`expiry` bigint(20) NOT NULL デフォルト '0 ',
? ?`data` が NULL ではありません、
? ?? ?KEY `expiry` (`expiry`)
? ) ENGINE= MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
sesskey は SESSION ID、expiry は SESSION データの保存に使用されます。
デフォルトでは、SESSION データはファイル モードで保存されます。データベース モードで保存したい場合は、各 SESSION オペレーションの処理関数を再定義する必要があります。 PHP には


session_set_save_handle() 関数が用意されています。もちろん、この関数を使用して SESSION 処理プロセスをカスタマイズする必要があります。 PHP での設定: ('user');
?>
次に、この関数には 6 つのパラメーターがあります:
session_set_save_handler ( string open, string close)。 、string read、string write、string destroy、string gc )
各パラメータは、各操作の関数名です。これらの操作は、オープン、クローズ、読み取り、書き込み、破棄、ガベージ コレクションの順序です。詳細な例は PHP マニュアルにあります。ここでは OO を使用してこれらの操作を実装します。詳細なコードは次のとおりです。 🎜>クラス My_Sess
{
? {
? ???$domain = '.infor96.com' ?? ?//GET/POST 変数メソッドを使用しないでください
? ????ini_set('session.use_trans_sid',? ? 0);
?//ガベージ コレクションの最大存続期間を設定します。 time
? ???ini_set('session.gc_maxlifetime',? MY_SESS_TIME);
? //COOKIE を使用して SESSION ID を保存する方法?ini_set( 'session.use_cookies',? ?? ?1);
? ?? ???ini_set('session.cookie_path',? ?? ?'/');
? ?// デフォルトのファイルの代わりにセッション ID を保存する COOKIE を複数のホストで共有します
? ???session_module_name('user');
? ???//対応するメソッド名を定義します各 SESSION 操作:
? ??session_set_save_handler(
? ?? ?? ?? ?array('My_Sess', 'open'),? ?//静的メソッド My_Sess:: open()、以下同様。
? ?? ?? ?? ?array('My_Sess', 'close'),
? ?? ?? ?? ?array('My_Sess', 'read'),
? ?? ?? ?? ?array('My_Sess', 'write'),
? ?? ?? ?? ?array('My_Sess', 'destroy'),
? ?? ?? ?? ?array('My_Sess', 'gc')
? ?? ???);
? ? }? ?//関数
を終了? ? function open($save_path, $session_name) {
? ?? ???true を返します;
? ? }? ?//関数
を終了? ? function close() {
? ?? ???グローバル $MY_SESS_CONN;
? ?? ???if ($MY_SESS_CONN) {? ? //关闭データベース库连接
? ?? ?? ?? ?$MY_SESS_CONN->Close();
? ?? ???}
? ?? ???true を返します;
? ? }? ?//関数
を終了? ? function read($sesskey) {
? ?? ???グローバル $MY_SESS_CONN;
? ?? ???$sql = 'SELECT data FROM sess WHERE sesskey=' 。 $MY_SESS_CONN->qstr($sesskey) 。 ' AND 有効期限>=' 。 time();
? ?? ???$rs =& $MY_SESS_CONN->Execute($sql);
? ?? ???if ($rs) {
? ?? ?? ?? ?if ($rs->EOF) {
? ?? ?? ?? ?? ? return ";
? ?? ?? ?? ?} else {? ? //SESSION ID の SESSION データ
? ?? ?? ?? ?? ? $v = $rs- >フィールド[0];???? $rs->?? ?? ?? ?? ?//終了 if
? ? }? ?//関数
を終了? ? function write($sesskey, $data) {
? ?? ???グローバル $MY_SESS_CONN;
? ?? ???
? ?? ???$qkey = $MY_SESS_CONN->qstr($sesskey);
? ?? ???$expiry = time() + My_SESS_TIME;? ? //設置期間
? ?? ???
? ?? ???//書き込みセッション
? ?? ???$arr = array(
? ?? ?? ?? ?'sesskey' => $qkey,
? ?? ?? ?? ?'expiry'??=> $expiry,
????'データ'? ?? ???$MY_SESS_CONN->Replace('sess', $arr, 'sesskey', $autoQuote = true);
? ?? ???true を返します;
? ? }? ?//関数
を終了? ? function destroy($sesskey) {
? ?? ???グローバル $MY_SESS_CONN;
? ?? ???$sql = 'DELETE FROM sess WHERE sesskey=' 。 $MY_SESS_CONN->qstr($sesskey);
? ?? ???$rs =& $MY_SESS_CONN->Execute($sql);
? ?? ???true を返します;
? ? }? ?//関数
を終了? ? function gc($maxlifetime = null) {
? ?? ???グローバル $MY_SESS_CONN;
? ?? ???$sql = '期限切れの sess WHERE から削除します。 time();
? ?? ???$MY_SESS_CONN->実行($sql);
? ?? ???//定期的な表セッションの削除操作により、碎片、
が発生しやすくなります? ?? ???// したがって、フレームの復元中にこのテーブルに対して宣伝操作が実行されます。 ?? ???$sql = 'テーブル最適化セッション';
? ?? ???$MY_SESS_CONN->実行($sql);
? ?? ???true を返します;
? ? }? ?//関数を終了
}? ?///:~
// ADOdb をデータベース抽象層として使用します。
require_once('adodb/adodb.inc.php');
//データパッケージ構成项、構成ファイル中に挿入可能
$db_type = 'mysql';
$db_host = '192.168.212.1';
$db_user = 'sess_user';
$db_pass = 'sess_pass' ;
$db_name = 'sess_db';
// 作成データベース接続、これは完全なローカル変数です。
$GLOBALS['MY_SESS_CONN'] =& ADONewConnection($db_type);
$GLOBALS[ 'MY_SESS_CONN']->Connect( $db_host, $db_user, $db_pass, $db_name);
//初期化 SESSION 設定、session_start() の前に実行する必要があります!!
My_Sess::init();
?>

五、保留問題

ウェブサイトのアクセス量が非常に大きい場合、SESSION の会話書き込みセッションは頻繁にデータ アクセスを実行するため、効率が明らかに低下する可能性があります。 SESSION
データは一般にそれほど大きくはなく、C/Java で複数のオンライン手順を書き込むプログラム、HASH テーブルを使用して SESSION データを保存し、socket
通信を介してデータの書き込みを行う、このような SESSION
を考慮します。さらに、これらはすべて私自身の単なるアイデアであり、実践されていません。
?



声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
前の記事:PHP保険次の記事:PHP保険