目次 †
名称 †
- xpdk
- xenowire pukiwiki decentralization kit
- ゼノワイア PukiWiki 分散化キット
概要 †
PukiWiki を、異なるネットワーク上にある複数サーバで分散運用するためのキットです。
BugTrack/763 - PukiWiki-dev の rsync とは違う方法で分散します。
背景 †
物理的に隔絶されている安価なレンタルサーバを束ねて使用するために開発されました :D
サンプルサイト †
- http://d.xenowire.net/
- 使用データ : 2009 年 07 月 01 日〜 2009 年 07 月 28 日
- 費用対アクセス : 約 250 PV/円
- 費用合計 : 約 400 円/月
- PukiWikiデータ
- ページ数 : 1773 ページ
- AutoLink : 有効 (3 bytes)
- robots : index, follow
- アクセス数
- クローラ除く : 約 90,000 PV/月
- クローラ含む : 約 100,000 PV/月
- 製薬・医療系企業 30%, 大学・病院・研究機関等 45%, 行政機関等 5%, 一般 13%, 一般(携帯端末) 7%
- アクセス傾向
- 営業日/平日、朝〜夜にかけて高負荷
- 夕方〜早朝にかけて携帯端末のアクセスが顕著
- 付加スクリプト等
- マスター 1 つ
- スレーブ 1 つ
- マスターとスレーブは異なる SP 所管
- マスターとスレーブは異なる AS 所管
- DNS ラウンドロビン
xpdk 構成例 †
- マスター 1 つ
- スレーブ 3 つ
- DNS ラウンドロビンにより、ユーザーは xpdk を意識することなく利用
- マスター 2 つ (各々スレーブ兼任, うち 1 つはバックアップ)
- スレーブ 2 つ
- DNS ラウンドロビン
- マスター 1 つ
- スレーブ 2 つ
- 各サーバーへは違う URL でアクセス
特徴 †
- サーバ負荷分散
- マスター・スレーブ構成
- 複数のスレーブサーバを指定可能
- 複数のマスターサーバを指定可能
- マスターとスレーブの兼任可能
- ネットワーク負荷分散
- 異なる場所にある ( 異なるネットワーク上にある )PukiWiki の同期が可能
- [ 1 ネットワーク ] 対 [ n サーバ ] + [ ロードバランサ ] のような、
ネットワーク負荷の集中しない構成が可能
( 同じネットワーク上にある PukiWiki の同期も無論可能 )
- 冗長性
- いずれかのサーバが動作していれば閲覧可能
- いずれかのマスターサーバが動作していれば編集可能
- スレーブを編集しようとした場合、自動的にマスターに転送
- Alive チェックにより、ダウンしているサーバは無視
- 即時性
- マスターの更新は即時全スレーブへ
- マスターに投稿される POST データをスレーブに転送
- rsync 等ファイルレベルでの同期は利用しません
- ファイアウォール ポリシーへの依存度の低さ
- 同期には Outbound HTTP/HTTPS のみ使用
動作に必要な環境 †
問題点 †
- マスターが複数ある場合、マスター同士での更新の衝突の検出ができない
- DNS ラウンドロビンと組み合わせる場合、ダウンしているサーバーの検出ができない (DNS ラウンドロビンの問題)
- Alive チェック用スクリプトを用意し独自の負荷分散をする?
- レンタルサーバのダウン率は低いので問題なし?
ToDo †
- パッチ作業を必要最低限にし、導入を容易にする
- ユーザーによるアクセスをトリガとしてマスターをチェックし、サーバダウン中に更新されたデータがあれば取得、適用する
ファイル構成 (xpdk 0.1.3) †
pukiwiki_root/
├index.php ( パッチ )
├syncconf.php - 同期設定ファイル
├syncfunc.php - 同期に使用される関数など
├syncrecv.php - 受信用スクリプト
├syncsend.php - 送信用スクリプト
├lib/
│├auth.php ( パッチ )
│└html.php ( パッチ )
└plugin/
├edit.inc.php ( パッチ )
├freeze.inc.php ( パッチ )
├newpage.inc.php ( パッチ )
├rename.inc.php ( パッチ )
└unfreeze.inc.php ( パッチ )
状態 †
案とメモ †
- index.php への POST をリモートの index.php に転送するだけでいいかも?
- プラグインに個別にパッチを当てる必要がない
- lib/edit.php だけはダイジェストチェックがあるのでパッチ必要
- 転送する cmd または plugin を指定
- search プラグインの POST は転送しない
- 等
- 転送がループしないように SERVER_ADDR チェック
- 全PukiWikiの管理パスワードを同一に設定
- POST 転送元の検証
- REMOTE_ADDR
- 同期用パスワードの設定 ( 転送元が POST に混ぜて送る )
各サーバに配置する xpdk.php :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
<?php
//
// 設定 {
//
// 実装時には設定は別ファイルにして xpdk_sync() で include する
//
// サーバIPアドレス => PukiWiki への連想配列
$g_xpdk_svs = array
( '000.000.000.001' => 'http://pkwk1.xenowire.net/index.php'
, '000.000.000.002' => 'http://pkwk2.xenowire.net/pukiwiki/index.php'
, '000.000.000.003' => 'http://editor:editor@pkwk3.xenowire.net/pukiwiki/index.php'
, '000.000.000.004' => 'https://pkwk3.xenowire.net/pukiwiki/index.php'
);
// 同期用パスワード
$g_xpdk_pass = 'xpdkpassword';
// 転送する cmd または plugin の指定
$g_xpdk_cmds = array
( 'edit'
, 'rename'
, 'freeze'
, 'unfreeze'
);
//
// } 設定
//
// 同期用関数
function xpdk_sync()
{
global $g_xpdk_svs, $g_xpdk_pass, $g_xpdk_cmds;
// リクエストのチェック
if( count( $_POST ) == 0 )
return;
//
$args = array_merge( $_GET, $_POST );
// 転送する cmd または plugin のチェック
if( !in_array( $args['cmd'], $g_xpdk_cmds )
&& !in_array( $args['plugin'], $g_xpdk_cmds )
)
return;
// ブラウザからの POST であれば他サーバに転送
if( $args['xpdk_pass'] != sha1( $g_xpdk_pass )
|| !array_key_exists( $_SERVER['REMOTE_ADDR'], $g_xpdk_svs )
)
{
// 他サーバに転送
// 同期用パスワードを混ぜる
$_POST['xpdk_pass'] = sha1( $g_xpdk_pass );
// 転送
foreach( array_keys( $g_xpdk_svs ) as $ipa )
{
// 自分には転送しない
if( $ipa == $_SERVER['SERVER_ADDR'] )
continue;
xpdk_post( $g_xpdk_svs[ $ipa ], $_GET, $_POST );
}
}
}
// $u + $g に $p を POST する関数
function xpdk_post( $u, $g, $p )
{
// 実装済みなので省略
}
?>
|
各サーバの index.php に追記 :
1
2
3
4
5
6
|
<?php
include 'xpdk.php';
xpdk_sync();
?>
|