RTMPの冗長構成って面倒ですよね
ストリーミングプロトコルのRTMP(Real Time Messaging Protocol)を冗長するためには
・サーバ側でActionScriptをガリガリ書く
・Flashプレイヤー側でActionScriptをガリガリ書く
の二通りあると思っているのですが、ActionScriptなんてもう書きたくない(※個人の感想です)じゃないですか。
さっくり今あるもので出来ないかなー。
概要
GSLBの機能を使うとDNSサーバ側でサービスを監視して異常が合った場合にDNSの問い合わせに対して、該当のIPを除外してくれます。
そのため、DNSレベルでの障害機器を切り離す事ができます。
(もう既につながっている人は救えませんが、次再接続に来れば違うサーバにつながる。)
この機能にRTMPの監視を実装して、オープンソースのFlashプレイヤーを使って手軽に冗長配信を考えてみました。
使うもの
OS:CentOS 7
DNSサーバ:gdnsd
RTMPチェック:rtmpdump
rtmpサーバは事前に複数台立てておいてください。
(それぞれ、アプリケーション名とストリームキーは同じものを利用する。)
gdnsdのインストール
こちらを参考にインストールしました。
http://qiita.com/jh1vxw/items/7ce5d14e9f964f001257
rtmpdumpのインストール
gitでソースを取ってきます。
$ mkdir ~/git
$ cd ~git
$ git clone git://git.ffmpeg.org/rtmpdump
$ cd rtmpdump/
$ make SYS=posix
$ sudo meke install
$ sudo cp -p /etc/ld.so.conf /etc/ld.so.conf.org
$ sudo vi /etc/ld.so.conf
$ diff /etc/ld.so.conf /etc/ld.so.conf.org
2d1
< /usr/local/lib/
$ sudo ldconfig
rtmpdumpの動作確認
$ rtmpdump -V
RTMPDump v2.4
(c) 2010 Andrej Stepanchuk, Howard Chu, The Flvstreamer Team; license: GPL
ERROR: You must specify a hostname (--host) or url (-r "rtmp://host[:port]/playpath") containing a hostname
成功!
以下のようなエラーが出た場合はライブラリの設定が上手くいっていない可能性があります。
rtmpdump: error while loading shared libraries: librtmp.so.1: cannot open shared object file: No such file or directory
gdnsdの設定
plugins = {
multifo = {
rtmp = {
up_thresh = 0.00000001
service_types = rtmpdump
fms1 = XXX.XXX.XXX.1
fms2 = XXX.XXX.XXX.2
fms3 = XXX.XXX.XXX.8
}
}
}
service_types = {
rtmpdump = {
plugin = extmon
cmd = ["/usr/local/bin/rtmpdump", "-vr", "rtmp://%%ITEM%%/{アプリケーション名}/{ストリームキー}", "--stop", "2", "-o", "/tmp/test%%ITEM%%"]
interval = 30
timeout = 5
up_thresh = 5
ok_thresh = 3
down_thresh = 2
}
}
$TTL 86400
@ SOA ns1 hostmaster (
2016092600 ; serial
7200 ; refresh
30M ; retry
3D ; expire
10 ; ncache
)
@ NS {gdnsdプライマリサーバ}.
NS {gdnsdセカンダリサーバ}.
fms 10 DYNA multifo!rtmp
動作確認
gdnsdの起動
$ sudo /usr/sbin/gdnsd start
gdnsdで現在の状態確認
http://{gdnsdのアドレス}:3506/
すべて正常です。
digで確認
$ dig fms.example.com
(略)
;; ANSWER SECTION:
fms.example.com. 10 IN A XXX.XXX.XXX.8
fms.example.com. 10 IN A XXX.XXX.XXX.1
fms.example.com. 10 IN A XXX.XXX.XXX.2
(略)
XXX.XXX.XXX.8のサーバを止める
http://{gdnsdのアドレス}:3506/で確認
XXX.XXX.XXX.8がDOWN表示になりました
digで再度確認
$ dig fms.example.com
(略)
;; ANSWER SECTION:
fms.example.com. 10 IN A 124.241.66.1
fms.example.com. 10 IN A 124.241.66.2
(略)
XXX.XXX.XXX.8が切り離されましたね。
この後、サーバを再度復帰させるとまた元の状態に戻ります。
現状の問題点
- サーバのRTMPの生死のみが判断のキーになっているので、エンコーダ側のエラーに対応が出来ない。
- エンコーダが止まっていても、サーバのアプリケーション名が生きているかぎり EXIT_STATUSが"0"が返ってくるため。
- nginx-rtmp-moduleを使ったRTMPサーバの監視が出来ない。
- 正常時にもrtmpdumpでRTMP_ReadPacket, failed to read RTMP packet headerのエラーが発生してしまう。
その他の用途
冗長も大事なんですが、これを使えば、日本のユーザには日本のサーバから、アメリカのユーザにはアメリカのサーバから・・・
みたいな事もかんたんにできるはずです。たぶん。(この辺 https://github.com/gdnsd/gdnsd/wiki/GdnsdPluginGeoip)
むしろこっちのほうが大事なんじゃねえかみたいなツッコミもありますが・・・・