PowerCMS XのSearchEstraierプラグイン(サイト内全文検索機能)で利用している「Hyper Estraier」にはP2P機構が備わっています。AWSのEFSに検索インデックスを置いた場合、EFSのパフォーマンスの兼ね合いで時々トラブルが発生することがあり都度対策が施されているのですが、「そもそもestcmdで直接検索インデックスを操作するのではなく、MySQLのように何かサーバーがあればいいのに…」とぼんやり考えていました。そのサーバー機能を提供するのがP2P機構でした。
ノードサーバーの立ち上げ
まずサーバーディレクトリを作成します。
estmaster init p2p
PowerCMS Xのワーカーで通常通り検索インデックスを作成(ギャザラの実行)します。その後、P2P機構のサーバーディレクトリにコピーします。
cd /path/to/powercmsx
sudo -u nginx php ./tools/worker.php --task_ids searchestraier_update_idx --verbose
cd /path/to/support/search
cp -R faq p2p/_node/
ノードサーバーを設置し、ノードマスターを起動します。-bgオプションを記述していますが、実際にはSupervisorでデーモン化しました。
estcmd meta p2p/_node/faq label "faq"
estmaster start -bg p2p
これでhttp://localhost:1978/node/faq/search_uiにアクセスするとfaqノードの検索ができるようになっています。外部からアクセスできるようにnginxのリバースプロキシを設定しhttps://rd.net-heroes.jp/estraier/node/faq/search_uiでもアクセスできるようにしました。
検索を実行
先のURLを開くと検索ボックスが表示されるので、phraseに「再構築」と入力して検索をすると結果が表示されます。また、attributeに「@netheroes-tags STRINC __ファイル出力__」と入力すると属性検索も可能です。
コマンドラインでもノードサーバーを検索することができます。この時、結果をXMLで受け取ることもできます。
estcall search -attr "@netheroes-tags STRINC __ファイル出力__" -vx http://localhost:1978/node/faq
文書の追加
ノードサーバーに対して文書を追加する場合は、http://localhost:1978/node/faq/put_doc?draft=[str]にアクセスするかコマンドestcall put -auth user password http://localhost:1978/node/faq /path/to/draft_file.estを実行して登録できます。登録が完了するとサーバーディレクトリ(p2p/_node/faq)のファイルも更新されているようで、ノードマスターを停止→起動しても登録したドキュメントは表示されました。
PowerCMS XのSearchEstraierプラグイン設定でインデックスのパスをサーバーディレクトリ(p2p/_node/faq)にするのは不可です。estcmdによる直接のインデックス更新は上手くいきません。
ギャザラを実行した時
ギャザラ(estcmd gather…つまりPowerCMS Xの「Hyper Estraierインデックスの再構築」タスク)を利用してインデックスの洗い替えをした場合、サーバーディレクトリに反映してノードマスターを停止→起動するとインデックスファイルの内容が反映されました。
まとめ
PowerCMS Xでオブジェクトを更新した際にestcall putやestcall outでノードサーバーのインデックスを更新したり、MTEstraierSearchタグの検索をestcall searchで取得できたりすると良さそうに感じます。検索サーバーをCMSと別インスタンスにした場合、estcall searchのノードURLを他のサーバーのIPにするとXMLが取得できるのかな…?
ノードサーバーを利用した場合とestcmdで直接インデックスを操作した場合を比較して可用性が違うのか等、興味があります。(ドキュメントにデータベースを内包したプロセスをシステムに常駐
とあるので、ノードサーバーを利用した方がパフォーマンスは良いのでは?)
2024年11月18日追記:別インスタンスで検索サーバー化
PowerCMS Xを配置しているサーバーとは別のサーバーにHyper Estraierをインストールし、estmasterでサーバーを立ち上げました。そして、SearchEstraierプラグイン内にある下記処理をestcallで指定のノードサーバーに対し実行するようにしてみました。
- オブジェクトの内容を検索インデックスに登録する処理(
estcmd put) - オブジェクトを検索インデックスから削除する処理(
estcmd out) - オブジェクトを検索する処理(
estcmd search)
コードの変更例は下記の通りです。ひとまずコマンドやURLを直書きしました。
- $command = "{$estcmd_path} put{$ngram} {$data_dir} {$out}";
+ $command = "/usr/local/bin/estcall put -auth [username] [password] http://172.26.7.128/node/{$node_name} {$out}";
- $command = "{$estcmd_path} out {$data_dir} {$url}";
+ $command = "/usr/local/bin/estcall out -auth [username] [password] http://172.26.7.128/node/{$node_name} {$url}";
その結果、オブジェクトの更新や削除が別インスタンスのノードサーバーに反映され、ノードサーバーの検索インデックスに基づいてMTEstraierSearchタグの処理結果が表示されるようになりました。

検索インデックスファイルは高速なディスクに置いた方が良いと思うので、検索サーバーを複数台準備して冗長化する場合はどのような仕組みにするのかなと考えています。サーバーの検索インデックスファイルの共有はできないので、純粋に複数台にHTTPリクエストを出すしかないかも。(レプリケーション機能があればなぁ)