2016-04-14 4 views
1

このジョブをバックグラウンドで処理するためにSidekiqを使用してAWSサーバーでPDF文書を作成しています。SidekiqがAWS RDSで "ActiveRecord :: ConnectionTimeoutError:データベース接続を取得できませんでした(5.000秒待っています)"

[Rails]アプリケーションは、PDFファイルを作成する過程で、PDFファイルが作成されたかどうかをチェックするデータベースをプールします(間隔:2秒)。

今朝はSidekiq側にこのエラーメッセージが表示されました:

ActiveRecord::ConnectionTimeoutError: could not obtain a database connection within 5.000 seconds (waited 5.000 seconds) 

私はそれにMySQLとアマゾンRDSを使用しています。

一時的な解決策として、私は、しかし私は、これは単なる一時的なパッチで実現し、database.yml10から30poolパラメータを増加させました。

正しく修正するにはどうすればよいですか?

ありがとうございました

答えて

4

あなたのソリューションは実際には正しいものだと思います。 ActiveRecord::ConnectionPoolはスレッドベースです。つまり、データベースで作業したいスレッドごとに別々の接続を取得しようとします。他のスレッドからの接続が解放された場合、接続プールの合計サイズ(poolオプションがdatabase.ymlに設定されている)、ConnectionPoolはデフォルトで最大5秒待つように試みます。これらの5秒のタイムアウト後、ActiveRecord::ConnectionTimeoutError例外が発生します。

ここで、サイドキックは25 worker threads by defaultを使用します。したがって、より高い負荷の下では、最大25のジョブ(スレッド)が同時にdbにアクセスしようとすることは完全に可能です。 poolが10に設定されている場合、余分な作業者は他の作業者が完了するのを待たなければならず、多少のスレッドはあまりにも長く待たなければならなかったでしょう。

したがって、接続プールのサイズを少なくとも少し大きい値にしてから、25(操作した側の作業者の数)に変更するか、のように実行することでより少ない労働者でrun your sidekiqを追加します。最後に、常に十分な着信接続on the MySQL side(デフォルトでは100以上)を許可するようにしてください。

0

一般的に、ポーリングはソリューションとしてスケールされません。

アプリケーションの構造について詳しく知りませんが、concurrent-rubyのような宝石のいくつかの同時実行性の構造を活用したいと思うでしょう。

具体的には、PDFファイルの作成は、私はあなたの労働者を再設計になりFutureまたはPromise

の概念に非常に密接にマップします。

  1. はあなたのPDF生成コードはする必要があります約束する。生成されたPDFをデータベースに書き込むのに十分な時間だけdb接続を開く必要があります。それはpdf生成もしている間ではありません。

  2. 主なアプリケーションコードは、いつものようにサイドキックでPDF生成を約束する必要があります。データベースをポーリングする代わりに。このコードはPromiseが完了するか失敗するのを待つだけです。約束は正常に完了した場合、PDFがデータベースである、それが失敗した場合、あなたは例外トレースを持っているなどいつものように

、メーリングリストへ

関連する問題