2日続けてこんにちは。Heroku Meetup #6レポの続きです。
今回はCodeConsultingにおける質疑とその後の懇親会で聞いた内容についてのレポートですが、これは小西が直接聞き取れた内容と通訳の方の翻訳を脳内補完した超訳です。
事前にある程度の回答予測をした上で質疑に臨んでいたこともあって、書きながらどこまでが実際にHeroku技術者の言葉でどこからが自分の推測なのかよくわからない部分があります。(^^;;;
なので、そんなこと言ってねーよ!と言う部分があれば是非ご指摘ください。m(_ _)m
★Scalabilityに関する質問
高負荷なアプリケーションを作成する際に注意する点としては何を考慮するべきだろう?ということを考えながら用意した質問です。
Q. DBのconfigを変更することはできないか?
A. できない
Q. DATABASE_URLは何に使われているか?また削除しても問題ないか?
A.
Rubyアプリではデフォルトで接続するDBの定義として参照する
Dyno数に応じてコネクションが増える件については詳しく調査していないが、削除しても問題はないはず。
Q. Routerの限界を突破する方法はあるか?
A. 何言ってましたっけ???
リクエストがキューにたまってそれが順番に処理されていくというRouterの基本的なアーキテクチャの説明とアプリがレスポンスを30秒間返してこない場合はRouterが503を返す(この場合はH12のエラーログが出ます)と言った説明がされていたことは覚えています。
ログがでないケースについても言及されていた気がしますが、ちょっと忘れてしまいました。
Q. 複数のDB接続をDynoごとに振り分ける方法はあるか?
例えばセッションIDでDynoを振り分ける(いわゆるSticky Session)や、EvernoteのようにURLの一部にShardingIDを含めるなどの方法が考えられると思うが何か良い方法はないか?
A.
Sticky Sessionはやらない。
Evernote的なShardingIDの可能性については。。。何か方法を検討してみるよ。的な回答だったと思うがいまいち自信がない。
Q. 高負荷のアプリがある場合Herroku内の他のアプリやネットワークにどのような影響があるか?
A.
CPUやメモリに関してはDyno毎に振り分けられているので影響はないはず。ネットワークについては何かしらの影響があるかもしれない。
しかしHeroku上では毎秒15000リクエストをさばくような高負荷のアプリも存在するが特に問題は起きていない。
全体的にはだいたい予想通りの回答です。
DevCenterでもかなりの情報が公開されていますが、アーキテクチャに関してもシンプルで特にトリッキーなことをしていないというのが個人的なHerokuの印象です。(なので、こうした場合どうなるかという挙動の予測がしやすい。)
Routerに関しては終わってから調べたことも少しあるので後で補足します。
★Securityに関する質問
Q. Heroku内部での通信の安全性はどのように担保されているのか?
負荷テストの過程ではアプリを分割することやPostgreSQLをやめてRDSやNoSQL系のDBを使うこともなんとなく考えていました。
ただその場合それぞれのコンポーネント間の通信は全部SSLにしないといけないのがコスト高そうだなぁとか考えてふとHeroku内部の通信はどうなっているんだということを考えたのがこの質問の背景です。
A.
Routerから各Dynosへの通信はhttp。Firewallの中での通信なので問題ない。
ログサーバーとの通信もFirewallの中。特に暗号化はしていない。
PostgreSQLはFirewallの外。機密性の高い情報であるならSSLを使うべき。
Rubyの場合はデフォルトでSSLを使用する設定になっている。
Addonはそれぞれだが考えたかとしては暗号化が必要。
Herokuアプリから他のHerokuアプリをコールする際のSSLの必要性についてはアプリ毎に判断してください。
うーん(--
PostgreSQLはHeroku謹製だからFirewallの中だと思ってたよ。。。
よくよく考えると同じURLでクライアントPCからも接続できているのでそんなはずはないんだけど。
で、あらためてDevCenterのドキュメントを見に行ってみると、やっぱりRemoteから接続する場合以外はSSL不要みたいな書き方になってんじゃん!!!
この際Herokuアプリから接続する際にもSSL必須でも良い気がするんだけどどうなんだろう?
パフォーマンスはまだしも言語によってはSSL用のドライバがなかったりするのかも。
しかし、これPostgreSQLの方ではどうやってHerokuアプリとそうでないものを見分けてるんだろう???(IPの範囲とか?)
★番外
他社からの質問でHireFireというDynoを自動で上げ下げするツールが紹介されました。
これはレスポンスタイムを計測してプロセスを管理しているということだったので、どこでレスポンスタイムを計っているんだろう?と聞いてみたところ。。。
「多分Gem。RouterからforwardしたHttpリクエストのヘッダにはRouterがリクエストをアクセプトした時間が書かれているから、それから計算しているんだと思う。」(超訳)
みたいな回答。え?!それじゃRubyでしか動かないじゃん!と思ってサイト見に行くと本当にRubyでしか動かないみたいね。。。。(^^;;;
こういうのがアリならPlayPluginをAddOnとして作成するのもアリかも。(嬉しい人がいるかどうかは謎だけど。。。)
★補足1 - ルーターのIPアドレス
今回行った負荷テストはほとんど「https://xxx.herokuapp.com/....」というアドレスに対して行いました。
本番はもちろん正規のSSL証明書をインストールした独自ドメインです。やったことがある方はご存知かと思いますが、SSL証明書をインストールすると「xxx.herokussl.com」という新たなルーターホストが作成されます。
で、これらのホストについてnslookupでIPアドレスを引くと。。。
- xxx.herokuapp.com - 1個のアドレス
- xxx.herokussl.com - 3個のアドレス
が返ってきます。
ドキュメントには書かれてませんが、SSL-Endpointアドオンではルーターも冗長化されてるってことですかね。
今回のテスト(herokuapp.com)では1万スレッドからの同時アクセスでルーターがパンクしましたが、herokussl.comの方を使用すればもっと多くのアクセスに耐えたのかもしれません。
★補足2 - StressToolのhttps
StressTool自体もPlayで作っており、そこからのHttpsリクエスト送信にはPlayのWSクラスを使用しています。
テスト中はあまり気にしてませんでしたが、この時のSSLハンドシェイクが何回行われているかをソースコードで追ったところ。。。。どうもKeep-Aliveが効いているっぽい。(多分)
つまり各スレッドで最初の1回だけハンドシェイクが行われて後は同じコネクションを利用してリクエストを投げ続けていたと思われます。
これだとテストが実運用時のリクエストを忠実に再現していないという意味でよろしくないです。(実際にはハンドシェイクがもっとたくさん行われてルーターの負荷があがると思われる。)
しかし今回の場合は性能指標がDBのInsert件数だったので、まぁ結果オーライです。(^^;;;
逆にハンドシェイクを抜かせばSSLはそんなに重くないという傍証になっているかもしれません。(この辺知識先行で経験則がないです。。。)
ちなみにHerokuのアクセスログに記録される「service=XXms」という時間はアプリでの消費時間のみを表しているらしいので、ハンドシェイクを含むルーターでの消費時間は多分含まれていません。