-
Notifications
You must be signed in to change notification settings - Fork 2
ノンストップでノードを追加する場面の検証手順
- Droonga Clusterを2ノード以上の構成でセットアップしておく。 仮に、2ノード構成で各ノードの名前がnode0, node1とする。
- log-searchリポジトリの説明を参照して、Droongaノードの1台(仮に、node0とする)をスタンドアロンのログ検索サーバとしてセットアップしておく。
$ sudo service droonga-engine start
$ sudo service droonga-http-server start
$ sudo service td-agent restart
$ logger test1
$ logger test2
$ logger test3
$ curl "http://localhost:10041/d/select?table=Logs&limit=5&sortby=-timestamp&_=$(date +%s)"
これで、検索結果にtest1, test2, test3のログが出ていれば準備はOK。
node0上で以下のコマンドを実行し、ある程度の件数のログがあらかじめ溜まった状態にしておく。
$ max=1000; count=0; while [ $count -lt $max ]; do logger "log ${count}"; count=$(($count + 1)); done
node0上で以下のコマンドを実行しておき、1秒ごとにログが追記されるようにしておく。
$ interval=1; count=0; while true; do logger "Periodical log $count, at $(date)"; count=$(($count + 1)); sleep $interval; done
loggerと使わないで直接addする場合。
$ echo "{\"id\":\"$(date +%s)\",\"dataset\":\"Default\",\"type\":\"add\",\"body\":{\"table\":\"Logs\",\"values\":{\"host\":\"node0\",\"ident\":\"vagrant\",\"message\":\"direct add at $(date)\",\"type\":\"messages\",\"timestamp\":\"2015-04-28 17:19:09 +0000\"}},\"targetRole\":\"service-provider\"}" | \
droonga-request --host node1 --receiver-host node2
or
$ droonga-add --host node0 --receiver-host node0 --target-role service-provider \
--table Logs --value:host nodeX --ident vagrant \
--message "direct add at $(date)" \
--type "messages" --timestamp "2015-04-28 17:19:09 +0000"
別のコンソールで以下のコマンドを実行しておき、ログの件数が増えていくことを監視できるようにしておく。
DBを直接参照してレコード数を監視
$ while true; do echo "$(date) / Groonga@$(uname -n) / $(sudo -u droonga-engine -H groonga ~droonga-engine/droonga/databases/000/db select --table Logs --limit 0 | jq ".[1][0][0][0]")"; sleep 1; done
Droonga HTTP Server経由でレコード数を監視
$ while true; do echo "$(date) / HTTP@$(uname -n) / $(curl -s "http://localhost:10041/d/select?table=Logs&limit=0&_=$(date +%s)" | jq ".[1][0][0][0]")"; sleep 0.1; done
system.statusの結果を監視
$ while true; do droonga-system-status --host node0 --receiver-host $(uname -n) --pretty; sleep 1; done
or
$ while true; do echo "$(date) / $(curl -s "http://localhost:10041/droonga/system/status?_=$(date +%s)" | jq .)"; sleep 0.5; done
Droonga HTTP Serverが認識しているdroonga-engineノードの一覧を監視
$ while true; do echo "$(date) / $(curl -s "http://localhost:10041/engines?_=$(date +%s)" | jq .)"; sleep 1; done
転送バッファの内容を監視
$ while true; do ls ~droonga-engine/droonga/state/buffer/intentional/*/; echo "-----"; sleep 1; done
vagrantのホストOS側で操作する。
reset-nodes.sh:
#!/bin/bash
NODE0_SUDO="vagrant ssh node0 -- sudo"
NODE1_SUDO="vagrant ssh node1 -- sudo"
NODE2_SUDO="vagrant ssh node2 -- sudo"
wait_all() {
wait $NODE0_PID
wait $NODE1_PID
wait $NODE2_PID
}
node0_async_sudo() {
$NODE0_SUDO "$*" &
NODE0_PID=$!
}
node1_async_sudo() {
$NODE1_SUDO "$*" &
NODE1_PID=$!
}
node2_async_sudo() {
$NODE2_SUDO "$*" &
NODE2_PID=$!
}
echo "stopping services..."
$NODE0_SUDO service droonga-http-server stop
node0_async_sudo service droonga-engine stop
node1_async_sudo service droonga-engine stop
node2_async_sudo service droonga-engine stop
wait_all
echo "regenerating cluster informations..."
node0_async_sudo droonga-engine-catalog-generate --hosts=node0,node1
node1_async_sudo droonga-engine-catalog-generate --hosts=node0,node1
node2_async_sudo droonga-engine-catalog-generate --hosts=node2
wait_all
echo "deleting old data..."
node0_async_sudo rm -rf ~droonga-engine/droonga/state ~droonga-engine/droonga/*.log
node1_async_sudo rm -rf ~droonga-engine/droonga/state ~droonga-engine/droonga/*.log
node2_async_sudo rm -rf ~droonga-engine/droonga/databases ~droonga-engine/droonga/state ~droonga-engine/droonga/*.log
wait_all
if [ "$1" = "update" ]
then
SCRIPT_URL="https://raw.githubusercontent.com/droonga/droonga-engine/master/install.sh"
node0_async_sudo curl -s -o /tmp/install.sh $SCRIPT_URL
node1_async_sudo curl -s -o /tmp/install.sh $SCRIPT_URL
node2_async_sudo curl -s -o /tmp/install.sh $SCRIPT_URL
wait_all
node0_async_sudo env VERSION=master bash /tmp/install.sh
node1_async_sudo env VERSION=master bash /tmp/install.sh
node2_async_sudo env VERSION=master bash /tmp/install.sh
wait_all
fi
./copy-db.sh node0 node1
echo "restarting services..."
node0_async_sudo service droonga-engine start
node1_async_sudo service droonga-engine start
node2_async_sudo service droonga-engine start
wait_all
$NODE0_SUDO service droonga-http-server start
echo "done."
コピー時は、ログの流入を止めてから行う。 vagrantのホストOS側で操作する。
copy-db.sh:
#!/bin/bash
SOURCE=$1
DESTINATION=$2
if [ "$SOURCE" = "" ]
then
echo "you must specify the source host"
exit 1
fi
if [ "$DESTINATION" = "" ]
then
echo "you must specify the destination host"
exit 1
fi
echo "copying database from $SOURCE to $DESTINATION"
SOURCE_SUDO="vagrant ssh $SOURCE -- sudo"
DESTINATION_SUDO="vagrant ssh $DESTINATION -- sudo"
$SOURCE_SUDO service td-agent stop
$SOURCE_SUDO service droonga-http-server stop
$SOURCE_SUDO service droonga-engine stop
$SOURCE_SUDO rm -f /vagrant/databases.tar
$SOURCE_SUDO tar -cvz -f /vagrant/databases.tar -C ~droonga-engine/droonga/ databases
$DESTINATION_SUDO rm -rf ~droonga-engine/droonga/databases
$DESTINATION_SUDO tar -xv -f /vagrant/databases.tar -C ~droonga-engine/droonga/
echo "done."
ログ流入の復活
$SOURCE_SUDO service droonga-engine start
$SOURCE_SUDO service droonga-http-server start
$SOURCE_SUDO service td-agent start
コマンドのshorthandを用意
serf="sudo -u droonga-engine -H /home/droonga-engine/droonga/serf"
triple_logger() { for count in 0 1 2; do logger "$1 ($count)"; done; }
まず新ノードをjoinさせる
triple_logger "0: start join"
droonga-engine-set-role --host=node2 --role absorb-destination --verbose
triple_logger "1: role of the joining node is changed"
$serf query -rpc-addr node2:7373 join '{"node":"node2:10031/droonga","type":"replica","source":"node1:10031/droonga","dataset":"Default"}'
triple_logger "2: other nodes are registered to the joining node"
この時点で、droonga-http-server@node2は、接続先engineが存在しない(認識できていない)。 よって、全てが完了した後でdroonga-http-serverからserfクラスタへの再joinが必要となるが、現在はその仕組みがないので、手動でのdroonga-http-serverver再起動などの作業が必要である。何か対策を考えないといけない。
次に、他のノードから新ノードを見えるようにする。
$serf query -rpc-addr node1:7373 add_replicas '{"cluster_id":"8951f1b01583c1ffeb12ed5f4093210d28955988","dataset":"Default","hosts":["node2"]}'
triple_logger "3: joining node is registered to other nodes"
これで、各ノードは同一クラスタで、且つ新ノードのみが機能していない状態になる。 新ノード宛の書き込みメッセージの配送が始まるが、メッセージはバッファに溜まるようになっている。
次に、コピー元ノードの更新を止めて、データをコピーする。
droonga-engine-set-role --host=node1 --role absorb-source --verbose
triple_logger "4: source node is deactivated"
droonga-engine-absorb-data --source-host=node1 --host=node2 --verbose
triple_logger "5: data copying process is started"
$serf members -rpc-addr node2:7373
タイムスタンプの引き継ぎに失敗した場合は、以下のように手動でやる。
$serf members -rpc-addr node1:7373 -format json
$serf query -rpc-addr node2:7373 -format json accept_messages_newer_than "{\"node\":\"node2:10031/droonga\",\"timestamp\":\"2015-04-20T09:10:36.029638Z\"}"
triple_logger "6: completely copied"
最後に、roleを戻す。
droonga-engine-set-role --host=node1 --role service-provider --verbose
triple_logger "7: source node is activated"
droonga-engine-set-role --host=node2 --role service-provider --verbose
triple_logger "8: joining node is activated"