時雨堂のMQTTブローカーサービスsango。有料プランのスタンダードプランのサービスインは10/30だったのに、最近まで仕事で死んでたので、ざっくり使ってみたところだけレポートです。追記、、、したいけど時間作らないと。
Changelog (majorなもの)
- 2014/11/10 更新 : mosquitto-1.3.5のクライアントでTLS接続すると--insecureのオプションが無いとエラーになる件は、sangoがワイルドカードのサーバー証明書を送信しているのをmosquitto側が正しく認識できていない(ホスト名との完全一致のみ許していた)せいでした。ワイルドカードの処理をcURLなどを参考に追加したところ、sangoと通信できることがわかりました。
- 2014/11/7 10:25 更新 : 50KBを越えるメッセージの扱いについて情報をいただきましたので、更新しました。
- 2014/11/6 14:00 追記 : mosquittoのクライアントでの--insecure指定時のエラーは、サーバー側の証明書のタイプにmosquitto側が対応していないようでした。現状では--insecureを付けてテストを継続しています。
- 2014/11/6 追記:TLSのエラーの件でサポートしていただいてます。フォロー追記予定です。なお、GoやPythonで今すぐTLS試したい、という方は下記を参考になさって下さい。
無料プランと何が違うか
公式にはこちらをご参照ください:https://sango.shiguredo.jp/#plan
けっこういろいろ違います。
で、今回自分が注目したのは以下の点でした。
- クラスタ組んである
- TLSが使える
- Secure Websocketが使える
- 容量拡大
- 120,000メッセージまで送れる(無料プランだと50,000まで)
- メッセージサイズが50KBまで使える(MQTTのゲートウェイで集約してから投げるとか?)
クラスタ組んである
プラン登録すると、Broker AとBの2台のエンドポイントが見られるようになる。
で、AとBそれぞれにsubscriberのclientを接続しておいて、ブローカーAにメッセージを投げると、AとBの両方のsubscriberにメッセージが届く。ブローカーBに投げても、AとBの両方に届く。
これで冗長系を組める、、と思うのだけど、障害検知をどうするか、とか、通常はround robinで負荷分散する意味があるか、とか。いろいろあるが、今後の検討課題。
TLS使える
すでにGolangやPythondでの接続例はあるので、mosquittoでやってみました。
サーバ証明書のタイプによっては--insecureの指定は不可欠のようです。ソース追ってます。
client側の準備
参照:http://mosquitto.org/man/mosquitto-tls-7.html
- clientの側も証明書作る。(これはサーバー側で認証する場合。sangoでは不要っぽいです)
- まず自前CA作る
- 秘密鍵作る
- CSR作る(subjectは自前CAと変えておくのがいいらしい)
- CSRを自前CAの証明書で署名してclientの証明書の出来上がり
作例
$ openssl req -new -x509 -days 3650 -extensions v3_ca -keyout ca.key -out ca.crt
$ openssl genrsa -des3 -out client.key 2048
$ openssl req -out client.csr -key client.key -new
$ openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 3650
sango側の証明書
サービスを契約すると、ダッシュボードからダウンロードできます。ECC(楕円曲線暗号)使ってあって感動(何がw
ではつないでみます
subscriberはまずnon-TLSで
$ mosquitto_sub -h サーバー名 -p ポート番号 -t "トピックのルート/#" -u "ユーザー名" -P "パスワード"
TLS使ってpublishします。最初は-d (debug)オプション付き(追記:--certと--keyは無くても繋がりました)
$ mosquitto_pub -h サーバー名 -p ポート番号 -t "トピックのルート/tlstest" -u "ユーザー名" -P "パスワード" --cafile sangoの証明書 --cert クライアント側の証明書 --key クライアント側の鍵ファイル --insecure -d -m "メッセージの文字列"
これで、TLSでpublishしてnon-TLSでsubscriber側がメッセージを受け取れることがわかりました。
今度はsubscriber側もTLSで繫いでみます(追記:この場合も、--certと--keyは無くても繋がりました)
$ mosquitto_sub -h サーバー名 -p ポート番号 -t "トピックのルート/tlstest" -u "ユーザー名" -P "パスワード" --cafile sangoの証明書 --cert クライアント側の証明書 --key クライアント側の鍵ファイル --insecure -d
TLSでpubしてTLSでsub、もできました。
ただ、今のところ、--insecure
はずすと
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
でちゃうのが悔しい。せめてもっと詳しいエラー出せるようにソース追っかけてます。
(2014/11/10追記) ワイルドカードサーバー証明書の処理を追加したらうまくいきました
mosquitto-1.3.5のソースをとってきて、ワイルドカードサーバー証明書の処理のパッチをしたところ、--insecureのオプション無しで通信できることを確認できました。
パッチのデバッグの過程で、sangoがワイルドカードのサーバー証明書を送ってきていることも確認できました。(これはtcpdumpでも確認できていました)
まだ、パッチは他所からもらってきたコードの寄せ集めなので、公開は問題がありますが、もしご自分でやりたい場合には、mosquitto-1.3.5のソースのうち、lib/tls-mosq.c
の_mosquitto_verify_certificate_hostname()
関数内の
if(X509_NAME_get_text_by_NID(subj, NID_commonName, name, sizeof(name)) > 0){
name[sizeof(name) - 1] = '\0';
if (!strcasecmp(name, hostname)) return 1;
}
のstrcasecmp関数をワイルドカードのnameが来ても大丈夫な関数に変更すればよいかと思います。(他の箇所では完全一致が必要なので、strcasecmpを変更することはおすすめしません)
容量拡大
これまで6KBまでのメッセージが送ることができた。Githubのrepositoryへのcommitイベントを通知してもらうとき、データの量が4KBくらいだったので、ちょうど良かった。
50KBを120,000回送れるとなるとどうなるか?
1ヶ月は3600x24x30=2592000秒なので、120Kメッセージということは21秒に1メッセージ。
これがサンプリング間隔の目安になると思った。
5分間隔のサンプリングレートでも良いデータというものはけっこうある、というか、サーバー監視なんかではそもそもの観測値(loadaverageとか)が5分間の平均値だったりする。
50KBという容量は、1台のサーバーというより、1つのサービスを構成するサーバー群の観測データを1つにまとめておくことも可能なんじゃないかと思う。
すると、結果として15サービスくらいの監視の通信インフラとして機能させることができる。
これが月500円だとすると、まずまず。(実際にはfluentdやkibanaを動かすサーバーの費用もかかる)かな。
インフラ提供サービスを運営するとなれば、サーバー立ち上げるライセンス買うことになると思うけど、このラインより安くあげるのは、営業費用も考えるとなかなか大変。
気になっていたこと(TODOsから変更)
50KBを越えるとどういうエラーになるのか?
データを集約するときに、データ量の見積もりを誤ったらどうなるか?結構心配なのでテストしてみたい。、、と思っていましたが、コメントを頂いた通り、エラーではなく接続断になるようです。 送信する前にチェック大事ですね。