« 2012年8月 | メイン | 2012年10月 »

2012年9月

2012年9月14日 (金)

Heroku Meetup #6レポート その2

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」という時間はアプリでの消費時間のみを表しているらしいので、ハンドシェイクを含むルーターでの消費時間は多分含まれていません。

2012年9月13日 (木)

Heroku Meetup #6レポート その1

こんにちは。Heroku Meetup #6に参加してきました。

今回私はCode Consultingのプレゼンターの一人として発表させてもらいましたが(自分にとって)非常に有益な時間だったと感じています。
貴重な機会を与えてくださったHeroku社の方々に感謝します。

さて、そんな私のプレゼンですが後で懇親会で何人かの方から感想を伺ったところによると途中からよくわからなくなったという人多数。(--

あいすいません。m(_ _)m
昔から聴き手を置き去りにするプレゼンには定評があるんですが、今回は自分でも詰め込みすぎだったと思います。
また時間と同時通訳を考慮してカットした話も多いです。

なので、ここで完全版(?)の説明をお届けしたいと思います。当日使った資料は一応ここにありますが別に見なくても良いです。(^^;;;

 

★単純明快なシステム概要

まずネタにしたアプリですが、HTMLの装飾とかをとっぱらってシステムの骨子だけをとりだせばWEBフォームに入力するデータをDBにINSERTするだけという超単純なモノです。
例によってPlayframeworkで作りましたがサーバー側のコード自体は誰が作ってもこうなるだろう、というものでしたし別の言語を使っても似たり寄ったりだったでしょう。

はっきり言ってこれだけだとまったく箸にも棒にもかからないシロモノなわけですが、これがちょっと他と違っていたのは、そのサイトが毎年夏にやっている超有名テレビ番組から宣伝されるということです。

なので、URLがテレビに流れた直後に嘘みたいなアクセスが集中します。

 

★冗談みたいな性能要件

さて、このシステムをHerokuで実装するという前提で話を聞いたわけですが、割と最初の段階からボトルネックとなるのはDBのトランザクションだろうという予測がありました。

なので、「1秒に何件くらいINSERTできれば良いんですかね?」と聞いたところ最初の段階では900件という回答でした。
多めに見積もって1000件/秒と考えましたが、この時点ではそれ位はいくんじゃないかと思ってました。(以前に単純なテストでRonin * 2Dynosで200件/秒の登録ができることを確認していました)

。。。が、この数字が何故か数日後には5000件/秒になります。。。(--

どうもこの数字がユーザー数やPVと混同されたらしく、仮にPVがそれだけあってもトランザクション数はそこまでにはならない、ということをいくら説明してもとりあってもらえなかったようなんですね。

あとで別のところから聞いた話によるとテレビでURLが流れた場合、かなり高い確率で503 Service unavailabe(要するに過負荷でサーバーに接続できない)が返ってきてがっかり!となるため性能要件には神経質になっているということもあるようです。

なので結局僕のところでは秒5000でやってくれという話でおりてきました。。。(--
ちなみにこの時点で放送日まで2週間きってます。

最初から5000って言われてたらRDBは使わねーよ(--

 

★PostgreSQLを落とす

そんなこんなで負荷テストを開始します。
幸いなことに今回クライアントとHerokuとの契約はミートアップでも紹介されていたパッケージのさらに上位グレードの契約だったのでDynoもAddonもほぼ使い放題です。

そこでまずはPostgreSQLの限界を見極めることからテストを開始することにしました。
DBはそれほどキャッシュが必要なシステムとも思わなかったのでなんとなくIkaを選択します。

Heroku上ではPostgreSQLのconfigがMAX_CONNECTIONS=500で設定されていることはあらかじめ調べて知っていたのでとりあえずはこれを突破した時にどのような挙動になるかを確認することしにしました。
予算には余裕があるのでDynoは100台あげます。(^^;;;
Playframeworkの設定でスレッド数は50。コネクションプールは30です。

テストツールとしてはJMeterを使用して1000スレッドで100回ループさせました。(合計10万件のINSERT)

テスト条件 DB Dyno ServerThread ConnectionPool Client ClientThread LoopCount
Ika 100 50 30 JMeter 1000 100
結果 ConnectionError多数

予想通りの結果ですがDriverManager#getConnectionでエラーとなります。

HerokuはWebシステムとしてはDynoを増やすことで自在にScaleしますが、DBはScaleしないので単純にDynoだけ増やしても意味がないってことですね。

PostgreSQLのconfigは一切変更不可能なので500しかないコネクションをいかに有効に使うかが勝負になります。

そこで次にDynoの数を15まで減らしてみます。Playのスレッド数とコネクションプールは変更していないので最大コネクション数は「15 * 30 = 450」となるはずです。

テスト条件 DB Dyno ServerThread ConnectionPool Client ClientThread LoopCount
Ika 15 50 30 JMeter 1000 100
結果 250件/秒くらい

思ったほど数字伸びてないですね。(--;;;

 

★Heroku上にStressToolを実装

この時点では負荷テストのクライアントツールにローカルPC上のJMeterを使用していましたが、NewRelicで見る限りサーバー側の負荷がそれほどあがっているようには見えませんでした。にも関わらず設定をどのように変えてもあまり数字は伸びてません。

これには二つの理由が考えられます。

ネットワークレイテンシの問題

Herokuはアメリカ東海岸にあるので通信には毎回太平洋越えのネットワークレイテンシが発生します。レイテンシが平均100ms前後だとするとクライアント側で多数のスレッドがぐるぐるとループしていても各スレッドは最高でも100msに1回しかリクエストを発行していない計算になります。

クライアントリソースの問題

JMeterで1000スレッドを指定したとしてもクライアントPCの性能がそれに追いついていなければ実際に1000スレッド同時には動けません。
実際JMeterのログを検証しても早いスレッドはテストが半分完了する以前に終了していますし、最後の方は最初の競争に負けたスレッドがまとめて動いているような感じでした。
また、1000スレッド以上の負荷、例えば5000スレッド同時に動かそうとしてもクライアント側のソケット不足でまともに動かないという問題もあります。

要するにクライアント側の問題で実はHerokuにはたいして負荷がかかっていないんじゃないかというのがこの時点での推測です。

なので、ネットワークレイテンシのない東海岸からテストを実行するためにHeroku上にStressToolを作成することにしました。
ツール自体はURLをキックしたら指定個数のスレッドを起こして指定回数ループするだけのごく単純なモノです。

これをDyno100台あげて、100回キックすればHerokuルーターのラウンドロビンによっていい感じにクライアントの負荷が分散されるはずです。(^^;;;

テスト条件 DB Dyno ServerThread ConnectionPool Client ClientThread LoopCount
Ika 14 50 30 Heroku 5000 100
結果 1000件/秒くらい

とりあえず当初の目標は達成しましたね。(^^v

 

★Herokuのルーターを落とす

凶悪なStressToolを手に入れたので今度はHerokuのルーターがどこまでの負荷に耐えられるのか実験してみます。クライアントスレッド数を一気に倍の10000スレッドにしてみました。

テスト条件 DB Dyno ServerThread ConnectionPool Client ClientThread LoopCount
Ika 14 50 30 Heroku 10000 100
結果 503と接続エラー多数

ルーターのキューがあふれた場合はHerokuはログも吐かずに503を返すようです。
さらに負荷がかかった場合は多分接続エラーになっていると思います。(この辺はStressToolの作りが雑だったため正確には検証できてません。。。)

Webサーバーの動作としては割と一般的だと思いますが、503を返す場合はサマリだけでもログを出力してほしいですね。

ちなみにあとでログを調べたところ5000スレッドでもログサーバーは時々限界を越えているらしくところどころで「L10 - Drain buffer overflow」が記録されています。
最悪入力データをJSON化してログに書くだけにしようかとも思ったんですが、その案も没です。(そうは言っても一番多いところで秒間26000行以上のログが出力されてます。(^^;;;)

あまりに高負荷をかけるとHeroku社に怒られそうな気がするので1万スレッドでのテストは1度しかやっていません。(^^;;

 

★3DBでシャーディング

その後いろいろと設定を変えてテストしてみましたが、どうやっても数字はだいたい1000前後で止まります。このことから、これはもうDBがいっぱいいっぱいなんだろうと思いました。だけどDBのconfigは変えられないんですよねぇ。。。(--

そこで1DBをあきらめて複数のDBを使用して負荷分散させることを考えました。具体的には入力データの必須項目であるメールアドレスからハッシュをとってその値で使用するDBを切り替えます。
何故メアドのハッシュを使用するかというと要件の中にメアドの重複チェックだけは入っていたからです。

コネクションプールはPlayの標準のものが使えないので自前で実装。サイクリックにコネクションを使いまわしてオープンからある程度時間のたったものは破棄する単純な実装です。

DBは本当は同じグレードのものを使用するのが良いんですが、わざわざそのためだけにアプリを作るのも嫌だったので同一アプリ内でRoninとFuguを追加しました。

テスト条件 DB Dyno ServerThread ConnectionPool Client ClientThread LoopCount
Ika, Fugu, Ronin 14 50 30 * 3 Heroku 5000 100
結果 Out of memory
パラメータ調整しても900件/秒くらい

まったくもっていまいちです。。。(--

まず、最初に1DBの時と同じ設定ということで50スレッドと30のコネクションプールで動作させましたが、これはOutOfMemoryとなるDynoがいくつかでました。
実際にいくつのコネクションプールが作られたかはわかりませんが、最大で90個のコネクションがメモリに保持される計算になるので。
Herokuの各Dynoに割り当てられたメモリは512MB。けっして多くはありません。

そこでスレッド数やコネクションプール数を調整しながら何回か実行しましたが、結果は一番良い時で926件/秒。スループットは上がるどころか落ちてます。(--

正直この結果は予想外でしたが、結果から中で起こっていることを推測すると以下のようになります。

  1. 各Dynoは1DBの時と同じくらいの仕事量をこなしている
  2. 各DBの仕事量は分散によって3分の1に減っている
  3. 各DBの接続数(各Dynoでのコネクションプール数)は1DBの時と同じか少ないはず
  4. DBの同時トランザクション数は約3分の1のはず
  5. にも関わらず各トランザクションのレスポンスタイムはあまり変わっていない???
  6. スループット低下の原因はRonin, FuguがIkaよりもスペックが低いためと推測

いまいち5番目のレスポンスタイムの項が納得いかないですが、手持ちのデータから結果を無理やり説明しようとするとこうなります。

(他に何か説明可能な推測がありますかね?ちなみに自前のコネクションプールは1DBで使用した場合にPlay標準のコネクションプールを使用した場合よりも若干パフォーマンスが良いくらいなので多分問題ないです。)

エンジニアとして原因を追究したいという気持ちはあるんですが、これを検証しようとするのは結構難儀な作業です。
なんせ負荷テストをやっていた期間のログはほとんど5GB超。Papertrailでログのアーカイブはとっていましたが、翌日にならないとログを確認できないしそれをまともに開けるエディタもないという状況だったので。。。時間的にちと厳しい(--

まぁそれは置いておくとしても先のテストと併せて考えるとIkaの処理能力を使いきってないのでアプリの改修でスループットの向上が見込めることは間違いありません。
ただ、それも各DynoがすべてのDBに接続する可能性があるという条件の下では実装が難しくなる気がしました。
Herokuルーターが同一セッションのリクエストをどのDynoに飛ばすかは制御できないので、1Dynoが1DBにのみ接続するようなアーキテクチャもプラットフォーム側になんらかの手を入れない限り難しそうです。(今回のケースではDynoのIPアドレスからハッシュをとって接続DBを切り替えて後から重複チェックをするというのもギリギリありではあったんですが。)

先のOutOfMemoryの件もあるのでこの路線にはあまり未来が感じられずこの段階で一旦没としました。

 

★DATABASE_URLの削除

少し話はそれますが、この頃までにどうもConnectionErrorの発生する閾値が自分の予想よりも低いことに気が付いていました。
設定上で420コネクションしか使わないように調整してもConnectionErrorが発生することがあるのです。
PostgreSQL自体がいくらかのコネクションを予約していて500個全部が使えないのはわかるのですがなんか妙に少ない。

そこでDyno起動直後のセッション数をpg_stat_activity表から数えてみると、明らかに自アプリからの接続ではないコネクションが多数存在します。
それもDyno数に比例して増減しているようでした。

つまりパフォーマンスを求めてDyno数を増やせば増やすほど利用可能なコネクション数が減っていくという悪循環があったわけです。

これは要するにHeroku自体が裏でDBに接続して何かやっているということなんでしょうが、何をやっているのかは謎です。

試しに環境変数からDATABASE_URLを削除してみたところ謎のコネクションはなくなり、特にアプリの動作にも影響がなかったので結局削除したままで本番まで運用しました。

これで利用可能なコネクションが増えてConnectionErrorはでなくなりましたが、スループットの方にはそれほど極端な差は見られませんでした。

 

★Mecha出陣!

さて、もういい加減手詰まりな感があったんですがここで頼れるCTOから貴重なアドバイスが。

 

「EC2のラインアップを見ればPostgreSQLの各Planの土台となっているインスタンスはほぼ推測できる。
PlanによってCPUスペックがまったく違うからそれ相応のパフォーマンスアップが期待できるはず」

 

言われてEC2のインスタンスタイプのページを見に行くと確かにどこかで見たような数字が並んでいます。

これを見るとIkaの土台はおそらくラージインスタンス(4ECU)。
対して最上級プランのMechaの土台はハイメモリクアドラプルエクストララージインスタンス(26ECU)。
なんじゃ、そら。

Mechaは1ヵ月使うとさすがに予算オーバーなんですが、今回期間が短いので日割りにするとぎりぎりパッケージ予算内に収まります。
試しに実行してみた結果がこれ。

テスト条件 DB Dyno ServerThread ConnectionPool Client ClientThread LoopCount
Mecha 15 50 30 Heroku 5000 100
結果 4189件/秒

なんといきなりの4000件超!!!
なんじゃ、そら。

結局何度かテストを実施したところ一番良い時で4813件/秒まで行きました。 この数字はテスト全体でのスループットなので一番負荷の高いところから1秒を抜き出せば5000件/秒をクリアしています。

長々と書いてきて最終的な結論がパフォーマンスは金で買えということかと思うとかなりがっかりですが、まぁとりあえずまさかのミッションコンプリートです。

それにしてもCPUスペックは重要ですね。Heroku PostgresのページにはPlanの違いはCache sizeの違いとしか説明されてませんがCPUスペックも併記してほしいものです。

 

★放送当日

テレビの影響力を体感しましたがそれでも楽勝でした。(^^;;;

 

★質疑応答

このあとようやくメインイベントの質疑応答ですが、長くなったのでまた今度(^^;;;

2012年9月 7日 (金)

JavaでHerokuのWorkerを作成する

こんにちは。

このブログで何度も取り上げていることからもわかると思いますが、FLECTでHerokuアプリを作成する場合の第一選択は Playframework 1.2.xです。

これは当社にJavaの技術者が多いことが最大の理由ですが、Playの生産性は非常に高くパフォーマンスも良いので Webアプリを作る分には何の問題もありません。

その一方でHerokuのWorkerをJavaで作る場合はどうするのが良いんだろう?ということがずっと自分の中で課題として残っていました。
自前でmainを持つサーバーアプリケーションを作ってしまえば良いんですけど毎回それはさすがに面倒ですもんね。

そんな折ちょっとした示唆があってWorkerもWebアプリと一緒にPlayで作っちゃえば良いじゃん!ということに気がつきました。

以下はその方法です。

 

★PlayでJobを作成する

Playframeworkを使ったことのある人ならご存知かとは思いますが、PlayにはJobという強力なスケジューリング機構があります。

  • 何秒おき、何時間おきといった指定間隔でのインターバル実行
  • 毎日何時に実行

といったスケジューリングがAnnotationの宣言だけでできるのです。

この機能を使えばWebDynoを作る際にバックエンドJobも同時に組み込むことができますが、実のところそれはあんまりうれしくありません。

何故ならWebDynoは負荷によってスケールさせたいので何台起動するかがわからないからです。WebDynoが5台あがっていたらバックエンドJobも5回動作することになりますが、多くの場合これは意図するところではないでしょう。

なので定義したJobはWebDynoでは動かしたくありません。あくまでWorkerとしてだけ動かしたいわけです。

実はこれ簡単にできます。
以下にサンプルを示します。

 

import play.Play;
import play.jobs.Job;
import play.jobs.Every;
import java.util.Date;

//@Every("10s")
@Every("${jobtest.every}")
public class JobTest extends Job {
	
	public void doJob() {
		System.out.println("Job: " + new Date() + ", " + Play.id);
	}

}

 

上記は日付とPlayのフレームワークIDをコンソールに出力するだけの単純なJobです。
ポイントは@Everyの宣言でパラメータを使用していることです。

@Everyまたは@Onの引数に「${xxx}」というパラメータを使用した場合、その値はapplication.confから読み込まれます。

 

★application.confでスケジュールを定義

あとはフレームワークIDごとのスケジュールをapplication.confに追加してやればOKです。

デフォルトの設定で使っている場合は、

  • ローカル開発環境ではフレームワークIDなし
  • 本番(Heroku)環境では「%prod」

としている人が多いと思いますが、その場合の設定は以下のようになります。

 

jobtest.every=10s
%prod.jobtest.every=never
%worker.jobtest.every=5s
%worker.application.mode=prod

 

「%prod」「%worker」はそれぞれWebDyno用、WorkerDyno用のフレームワークIDです。
application.confでは同じキーの設定が複数回出現した場合は後に記述されたものが有効になるので、それぞれの環境毎の設定が行えます。
設定値を「never」とした場合そのJobは実行されなくなります。

最後の「%worker.application.mode=prod」はWorkerDynoでのPlayをProductionモードで動作させるための設定です。
DEVモードでは最初のHTTPリクエストが届くまでPlayは動作しないので、これがないとWorkerDynoはうまく動きません。

 

★Procfileの作成

最後にWorkerでもPlayを動かすようにProcfileを定義します。

 

web: play run --http.port=$PORT $PLAY_OPTS
worker: play run --http.port=$PORT --%worker

 

上の例ではWebDynoのフレームワークIDはHeroku環境変数「PLAY_OPTS」で、WorkerDynoのフレームワークIDは直接指定していますがこの辺はお好きなように。

WorkerDynoでもportにbindしてHTTPリクエストを待ちうけていますが、HerokuのルーターはWebDynoにしかリクエストをforwardしないのでここにHTTPリクエストが来ることはありません。

 

★メリット、デメリットを考える

いかがでしょう?(^^;

この方式ではWebDynoとWorkerDynoを一つのアプリケーション内で同時に作成できるのが最大のメリットです。
ローカル環境で開発/テスト中はWebとWorkerを1プロセスの中で同時に動かすことができます。

WebDynoでは使用しないJobのインスタンスがひとつ余計に作られることになりますが、その程度ではアプリの動作に何の影響もありません。

WorkerDynoはまったく使用しないWebアプリをまるまる抱えることになり、それはまぁちょっと気になるところではありますが。。。。
おそらくWorkerDynoのスペックもWebDynoと同等と思われるので気にすることはないでしょう。

WorkerDynoが待ちうけているportは多分外からアクセスできないと思うのでこれも問題ないはず。
ここにリクエストが飛んでくるようならそれはHerokuのセキュリティホールです。(^^;

Heroku上にステージング環境を持つ場合でもフレームワークIDでどうにでも対応できるので柔軟性にも問題なし。

他に何か考慮すべきことあるかな???

ん~、圧倒的にメリットの方が多い気がします。
こうして考えるとPlayでHerokuアプリを作る場合Workerはこれがスタンダードでも良い気がしますね。(^^v

採用情報

株式会社フレクトでは、事業拡大のため、
Salesforce/Force.comのアプリケーション
開発
HerokuやAWSなどのクラウドプラッ
トフォーム上でのWebアプリケーション開発

エンジニア、マネージャーを募集中です。

未経験でも、これからクラウドをやってみた
い方、是非ご応募下さい。

フレクト採用ページへ

会社紹介

株式会社フレクトは、
認定コンサルタント
認定上級デベロッパー
認定デベロッパー
が在籍している、
セールスフォースパートナーです。
heroku partnersにも登録されています。
herokuパートナー
株式会社フレクトのSalesforce/Force.com
導入支援サービス
弊社の認定プロフェッショナルが支援致します。
・Visualforce/Apexによるアプリ開発
・Salesforceと連携するWebアプリ開発
も承っております。
セールスフォースご検討の際は、
お気軽にお問合せください。
Powered by Six Apart