短い答え: @kch の答えを見てください。
310: HTML Content URL Required
1 つの Web dyno を実行しているときにエラーが発生しました。
関連するログは次のとおりです。
2012-07-04T19:11:13+00:00 heroku[router]: Error H12 (Request timeout) -> POST my-app-1111.herokuapp.com/campaigns dyno=web.1 queue= wait= service=30000ms status=503 bytes=0
2012-07-04T19:11:13+00:00 app[web.1]: cache: [GET /favicon.ico] miss
2012-07-04T19:11:13+00:00 heroku[router]: GET my-app-1111.herokuapp.com/favicon.ico dyno=web.1 queue=0 wait=0ms service=50ms status=304 bytes=0
2012-07-04T19:11:14+00:00 heroku[router]: Error H12 (Request timeout) -> GET my-app-1111.herokuapp.com/newsletters/1?cm=1 dyno=web.1 queue= wait= service=30000ms status=503 bytes=0
2012-07-04T19:11:14+00:00 app[web.1]: [error] CampaignMonitor error: The CreateSend API responded with the following error - 310: HTML Content URL Required
Request timeout
エラーを見て、GET my-app-1111.herokuapp.com/newsletters/1?cm=1
Campaign Monitor がすぐにすべてのニュースレター アセットに対してアプリをコールバックしていたことを思い出しました。
Web dyno の数を 2 つに増やしたところ、エラーが に変わり、312: Text Content URL Required
でタイムアウトすることがありましたGET my-app-1111.herokuapp.com/newsletters/1.txt
。それ以外の場合 (まだ 2 つの dyno がある場合)、API はエラーになりません (キャンペーンの下書きは実際に作成されました) が、アプリは他のアセットでタイムアウトしました (そして、サイトはまだ在庫を生成していましたApplication Error
)。これらのアセット タイムアウトの一部を次に示します。
2012-07-04T19:20:21+00:00 heroku[router]: Error H12 (Request timeout) -> POST my-app-1111.herokuapp.com/campaigns dyno=web.1 queue= wait= service=30000ms status=503 bytes=0
2012-07-04T19:20:24+00:00 heroku[router]: Error H12 (Request timeout) -> GET my-app-1111.herokuapp.com/assets/video/play.png dyno=web.1 queue= wait= service=30000ms status=503 bytes=0
2012-07-04T19:20:24+00:00 heroku[router]: Error H12 (Request timeout) -> GET my-app-1111.herokuapp.com/assets/video/pause.png dyno=web.1 queue= wait= service=30000ms status=503 bytes=0
Web dyno の数を 3 つに増やしても、まだアセットのタイムアウトが発生していました。
4 つの Web dynoを使用すると、プロセス全体が正常に完了することがありました (つまり、常にではありません!)。とにかく、常に成功したとしても、Campaign Monitor ニュースレターを作成するだけでも 4 つの dyno はコストがかかりすぎます。
CDN 上のアセット
asset_syncと fog のおかげでCDN アセット ホスト (Amazon S3) を使用するようにアプリを変換しましたが、Heroku の Campaign Monitor を使用してこの問題に戻りました。
私のアプリは資産を提供しなくなったため (Amazon S3 によって提供されます)、本質的に責任があるのは HTML を返すことだけです。
キャンペーン モニターに関しては、ニュースレターに基づいてキャンペーンを作成するために API にクエリを実行した瞬間に、ニュースレターをダウンロードするようにすぐに電話がかかってきます。これは実際には、2 つの並行した要求を送信することを意味します。1 つはニュースレターの HTML バージョン用で、もう 1 つはニュースレターのテキスト バージョン用です。API への元の呼び出しによって 1 つの dyno がブロックされ、すべてのアセットが CDN でホストされている場合、2 番目の dyno がそのトリックを行うと考えるでしょう。実際、1 秒の dyno が「並列」リクエスト (ニュースレターの HTML バージョンと TEXT バージョン) を処理するのを見てきました。ただし、ランダムなタイムアウトがまだあるため、信頼性は低くなります ( )。Error H12 (Request timeout)
2012-08-16T23:00:42+00:00 heroku[router]: Error H12 (Request timeout) -> POST my-app-1111.herokuapp.com/campaigns dyno=web.2 queue= wait= service=30000ms status=503 bytes=0
2012-08-16T23:00:42+00:00 heroku[router]: GET my-app-1111.herokuapp.com/favicon.ico dyno=web.4 queue=0 wait=0ms service=7ms status=304 bytes=0
2012-08-16T23:00:42+00:00 heroku[router]: Error H12 (Request timeout) -> GET my-app-1111.herokuapp.com/newsletters/1?cm=1 dyno=web.2 queue= wait= service=30000ms status=503 bytes=0
2012-08-16T23:00:43+00:00 app[web.2]: [error] CampaignMonitor error: The CreateSend API responded with the following error - 310: HTML Content URL Required
Heroku のサポートによると、これは、受信側の dyno が最終的に処理できるようになることを期待して、各リクエストを個別にディスパッチするためです。ここで何が起こっているかというと、場合によっては、投稿を行っているのと同じ dyno が 2 番目の要求を受信しているのですが、投稿要求を完了するには 2 番目の要求の結果が必要なようで、デッドロックします。
ソリューション
考えられる暫定的な解決策の 1 つはunicorn
、アプリ サーバーに unicorn を 2 つ使用することですworker_processes
。そうすれば、Heroku が忙しい dyno にディスパッチしても、2 番目のユニコーン リスナーがリクエストに応答します。
最終的には、unicorn
twoworker_processes
で使用することに加えて、正しい解決策は、 のような方法でリクエストを非同期的に処理し、必要に応じて Heroku ワーカー dyno をスピンアップするために使用することです。そのため、使用した分だけ支払うことになりますdelayed_job
。workless