これの途中経過。https://www.facebook.com/javascripting/posts/398389730217171
もっと良い手は無いかなぁ。。。とりあえず、身近で気楽そうなping監視版。
ソケット使う版はまたあとで。あと、ARPどうするかとか、メインサーバー生き返った時どうするかとかもあとで。ただ、heartbeatでいんじゃないの?という強い誘惑に勝てるかどうかは不明な今日この頃。。。
##node.jsで待機サーバーBを自動 ifconfig up する
サーバーA eth0 192.168.1.11 (メイン)
サーバーB eth0 192.168.1.12 (待機)
ルーターからのNATの宛先LAN側サーバーアドレス 192.168.1.10で
サーバーA に仮想IP eth0:1 192.168.1.10 を立てている時、
サーバーB から ping打って192.168.1.10を監視し、
死んでいたら、サーバーBの eth0:1へ仮想IP 192.168.1.10 を起動してサーバーを切り替える。
Internet
|
+--------+---------+
| GateWay |
+--------+---------+
| 192.168.1.1
|
| 192.168.1.0/24
+-----------+------------+------------+-----------+
| | //on err,
| 192.168.1.10(eth0:1) | //ifconfig eth0:1 192.168.1.10 up
| 192.168.1.11(eth0) | 192.168.1.12(eth0)
+--------+-------+ +--------+-------+
| Main Server A | | Sub Server B |
+--------+-------+ +--------+-------+
それぞれの機器のネットワークはたとえば下記な感じで設定しておく
【GateWay】example.comとか
WAN側 ***.***.***.***
LAN側 192.168.1.1
NATエントリ
LAN側ホスト プロトコル ポート番号 優先度
192.168.1.10 TCP 22-22 1
192.168.1.10 TCP 80-80 2
192.168.1.10 TCP 443-443 3
192.168.1.10 TCP 21-21 4
【Main Server A : OS Ubuntu 12.04 LTS】192.168.1.11
$sudo vi /etc/network/interfaces
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet static
address 192.168.1.11
netmask 255.255.255.0
network 192.168.1.0
gateway 192.168.1.1
dns-nameservers 8.8.8.8
【Sub Server B : OS Ubuntu 12.04 LTS】192.168.1.12
$sudo vi /etc/network/interfaces
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet static
address 192.168.1.12
netmask 255.255.255.0
network 192.168.1.0
gateway 192.168.1.1
dns-nameservers 8.8.8.8
ファイルの構成は次の通り
待機サーバーBへ設置してますが、両方に置いても可。
Sub Server B
home
└hoge
└kagemusya
├ping-ifup.js ... 0705 サーバーAの監視・障害時に仮想IPを起動する
├kage-start.sh ... 0705 サーバーB起動時用スクリプト rc.localへ設定
└log ... 0606
└kage-start-log.txt ... (自動生成)サーバーB起動時のログ
##pingで監視して、障害時にはifconfig upで仮想IPを起動する
*node.jsは、nvmでインストール済みです。
#!/home/hoge/nvm/v0.8.3/bin/node
//Vars
var targetAddr = '192.168.1.10';
var cmdPing = '/bin/ping';
var count = '3'; //pingパケット試行回数
var interval = 10000; //監視間隔
var aliveStr = '100% packet loss';
var tid;
var cmdIfconfig = '/sbin/ifconfig';
var nic = 'eth0:1';
var ifcmd = 'up';
//Modules
var sys = require('util');
var spawn = require('child_process').spawn;
//Go!
main(targetAddr);
//ping process
function ping(targetAddr, callback) {
clearInterval(tid);
tid = setInterval(function(){
var pingProcess = spawn(cmdPing, ['-c ' + count , targetAddr]);
pingProcess.stdout.on('data', function (data) {
var data = data.toString().split('\n').join();
var isOk =
data.indexOf(aliveStr) === -1 ;
var is = isOk ? ' is ok.' : ' is ng.';
console.log('============================================');
console.log('targetAddr ' + targetAddr + is);
console.log('stdout: ' + data);
if(isOk) {
//targetAddr is alive. 正常
}
else {
clearInterval(tid);
pingProcess.kill();
callback(isOk);
}
});
pingProcess.on('exit', function (code) {});
},interval);
}
//ifconfig process
function ifconfigUpDown(targetAddr) {
var ifup = spawn(cmdIfconfig, [nic, targetAddr, ifcmd]);
ifup.stdout.on('data', function (data) {
console.log('stdout: ' + data);
});
ifup.stderr.on('data', function (data) {
console.log('stderr: ' + data);
});
}
//do it!
function main(targetAddr) {
ping(targetAddr, function (isOk) {
ifconfigUpDown(targetAddr, isOk);
});
}
【修正履歴】
2012/08/02
'100% packet loss'じゃなければOK。に変更^^;微調整中。
2012/08/02
clearTimeoutとclearInterval書き間違えてた(^^;
'0% packet loss'は'1.0% packet loss'の場合もあるので' 0% packet loss'へ変更
2012/07/31
少しでも早く障害把握したいと思って、'Unreachable'と'100% packet loss'で
死亡確認してたけれど、pingの返事には'Request timed out'とか他にもいろいろ
あるので、結局最初の'0% packet loss'がひとつも無いという確認に変更。
早く確認したければ、pingパケット試行回数を減らす(精度とトレードオフ)とか他の手で。
注:この生存確認文字列aliveStrは、マシンによっても異なると思います。
2012/07/30
pingによるUnreachable検出に数十秒かかってしまっていたので、
ping -c 3 192.168.1.10 でループした方が検出速いんじゃないかな?ってことで
少し書き換えたら少し速くなった。
2012/07/30
昨日は192.168.1.11をpingで監視したんだけれど、192.168.1.10を監視に変更。
目的は192.168.1.10の監視なのに、192.168.1.10が死んで、192.168.1.11が
生きてるというケースもあるので。
##マシン起動時用スクリプト
上記のping-ifup.js を下記のような起動時用スクリプトの中に書いて、待機サーバーB 192.168.1.12の /etc/rc.local に置くと起動時にrootとして実行してくれるのでifconfig upも実行できる。
kage-start.shのパーミッションは0705とか実行権限を与えておく。rc.localだけで動かすなら0700でも良いかもしれない。
log用ディレクトリは /var/log 以下でも良いけど、ここではプロジェクト内の /home/hoge/kagemusya/log へ書き込み可で用意しました。
#!/bin/sh
#This is a Sub Server 192.168.1.12
#NAT IP eth0:1 192.168.1.10
#一応起動ログもとっとく
logFile=/home/hoge/kagemusya/log/kage-start-log.txt
echo "================================================" >> $logFile
date '+%Y/%m/%d %H:%M:%S.%N' >> $logFile
echo "${0}" >> $logFile
echo "i am $(whoami)" >> $logFile
#サーバーAの仮想IP 192.168.1.10を監視して、
#落ちてたら自分でeth0:1へ仮想IP 192.168.1.10を立ち上げるスクリプト
/home/hoge/nvm/v0.8.3/bin/node /home/hoge/nvm/v0.8.3/bin/forever start /home/hoge/kagemusya/ping-ifup.js
echo "start /home/hoge/kagemusya/ping-ifup.js" >> $logFile
#サーバーで動かしたいWebSocketアプリとか
/home/hoge/nvm/v0.8.3/bin/node /home/hoge/nvm/v0.8.3/bin/forever start /home/hoge/node/ws-app.js
echo "start /home/hoge/node/ws-app.js" >> $logFile
##rc.localへ設定する
これで、マシン起動時に上記のping監視が自動で立ち上がります。
#!/bin/sh -e
/home/hoge/kagemusya/kage-start.sh
exit 0
##今回作ったマシンのお会計です。
【サーバーA】
ベアボーンキット Shuttle XH61V ¥16,800
メモリ TRJ JM1333KSN-8GK(SODIMM DDR3 PC3-10600 4GBx2) ¥3,170
CPU Intel Core i3-2120 BOX (1155/3.30/3M/C2/T4) ¥9,760
SSD OCZSSD2-1VTXPL60G ¥5,980
----------------------------------------------
合計 35,710円
【サーバーB】
ベアボーンキット Shuttle XH61V ¥16,800
メモリ TRJ JM1333KSN-8GK(SODIMM DDR3 PC3-10600 4GBx2) ¥3,170
CPU Intel Celeron G540 BOX(1155/2.50/2M/C2/T2) ¥3,480
SSD SP060GBSSDV30S ¥4,870
----------------------------------------------
合計 28,320円
ちなみに、サーバーAとサーバーBをWebSocketのシンプルなレスポンスで比較すると同一
ネットワーク内でどちらも2~5ms、インターネット側の別のマシンからは、どちらも
10~15msということで、全然差はありませんでした。
まぁ、数千件の同時アクセスとかなら差が出るのかもしれませんが、そういう用途以外
ならサーバーBの構成でも十分という感じ。もし、お金をかけるなら回線側の方が効果あ
るかも?
ちなみに、私が現在業務で使ってるWebSocketマシンはAtomなので、サーバーBより安物
ですが、これも快適です^^。node.js & WebSocket 万歳!(^0^)/。