目次


名称

  • xpdk
  • (xenowire) pukiwiki decentralization kit
  • (ゼノワイア) PukiWiki 分散化キット


ソースコード @ GitHub


概要

PukiWiki を、異なるネットワーク上にある複数サーバで分散運用するためのキットです。
(BugTrack/763 - PukiWiki-dev の rsync とは違う方法で分散します。)

バージョン動作概要
xpdk1ブラウザからの POST リクエストをスレーブに転送
xpdk2スレーブがマスターに同期に必要なデータを要求
xpdk2.png


背景

物理的に隔絶されている安価なレンタルサーバを束ねて使用するために開発されました :D

特徴

  • サーバ負荷分散
    • マスター・スレーブ構成
      • 複数のスレーブサーバを指定可能
      • 複数のマスターサーバを指定可能
      • マスターとスレーブの兼任可能


  • ネットワーク負荷分散
    • 異なる場所にある ( 異なるネットワーク上にある )PukiWiki の同期が可能
    • [ 1 ネットワーク ] 対 [ n サーバ ] + [ ロードバランサ ] のような、
      ネットワーク負荷の集中しない構成が可能
      ( 同じネットワーク上にある PukiWiki の同期も無論可能 )


  • 冗長性
    • いずれかのサーバが動作していれば閲覧可能
    • いずれかのマスターサーバが動作していれば編集可能
      • スレーブを編集しようとした場合、自動的にマスターに転送
    • Alive チェックにより、ダウンしているサーバは無視


  • 即時性
    • マスターの更新は即時全スレーブへ
      • マスターに投稿される POST データをスレーブに転送
      • rsync 等ファイルレベルでの同期は利用しません


  • ファイアウォール ポリシーへの依存度の低さ
    • 同期には Outbound HTTP/HTTPS のみ使用


  • 共用レンタルサーバでも負荷分散可能


動作に必要な環境

  • PukiWiki
  • PHP4以上
  • 各サーバを識別できるホスト名


問題点

  • マスターが複数ある場合、マスター同士での更新の衝突の検出ができない
    • マスター同士の更新の衝突は無視する?
  • DNS ラウンドロビンと組み合わせる場合、ダウンしているサーバーの検出ができない (DNS ラウンドロビンの問題)
    • Alive チェック用スクリプトを用意し独自の負荷分散をする?
    • レンタルサーバのダウン率は低いので問題なし?


ToDo

  • パッチ作業を必要最低限にし、導入を容易にする
  • ユーザーによるアクセスをトリガとしてマスターをチェックし、サーバダウン中に更新されたデータがあれば取得、適用する


ファイル構成

xpdk2

 pukiwiki_root/
 ├lib/
 │├pukiwiki.php ( パッチ )
 │├xpdk2.php - xpdk2本体
 │└xpdk2_config.php - 設定ファイル
 └plugin/
  ├edit.inc.php ( パッチ )
  ├freeze.inc.php ( パッチ )
  ├newpage.inc.php ( パッチ )
  ├rename.inc.php ( パッチ )
  └unfreeze.inc.php ( パッチ )


xpdk1 (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 に転送するだけでいいかも?
    × POSTサイズ制限によりスレーブに転送できない場合がある。
    • プラグインに個別にパッチを当てる必要がない
      • 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
<?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
<?php
 
    include 'xpdk.php';
    xpdk_sync();
 
?>

トップ 編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード 新規 一覧 単語検索 最終更新 リンク元 ヘルプ 最終更新のRSS xenowire
Last-modified: Thu, 25 Jan 2018 15:13:49 JST