18

データベースのダウンタイムの後、Rails は最初にこのエラーを 1 回スローします。

ActiveRecord::StatementInvalid: NativeException: org.postgresql.util.PSQLException: 接続が拒否されました。ホスト名とポートが正しいこと、およびポストマスターが TCP/IP 接続を受け入れていることを確認してください。

それ以降、データベースがバックアップされた後でも、すべてのデータベース呼び出しで次のエラーが発生します。

ActiveRecord::StatementInvalid: ActiveRecord::JDBCError: この接続は閉じられました。

サーバーを再び稼働させるには、Rails サーバーを再起動する必要があります。私たちの製品エンジニアは、データベースに依存するすべてのサービスを元に戻すことなく、データベースのメンテナンスを行いたいと考えているため、これは私たちにとって理想的ではありません。だから、私は疑問に思っています.Railsにデータベース接続の再確立を自動的に試行させる方法、またはこの動作を取得するための推奨される方法はありますか?

私が試したこと:

データベース オプションで reconnect を true に設定しようとしましたが、これにより、個々のデータベース接続を強制終了でき、Rails は接続を再確立します。ただし、データベースの停止後はそうではありません。コマンドコンソールから呼び出すことで接続を元に戻すことができることがわかりました

ActiveRecord::ベース::確立_接続

レールが上記のコマンドを呼び出すためのクリーンな場所を見つけると、これが機能するでしょうか? 助言がありますか?

4

5 に答える 5

2

これは本当に醜い解決策ですが、うまくいくはずだと思います。

  • 以前と同じように、reconnect を true に設定します。

  • ファイルを編集し、メソッドを言うようにactiverecord-X.Y.Z/lib/active_record/connection_adapters/postgresql_adapter.rb変更しますreconnect!

    def reconnect!
      clear_cache!
      ActiveRecord::Base.establish_connection
    end
    

さらなる研究が必要です

  • 実際に動作するかどうかを確認する
  • Establish_connection を同時に数回呼び出していないかどうかを確認します (この場合、ロックが必要になります)。
  • このコードを配置するのに適した場所がないか確認してください。Ruby では実行時に任意のメソッドを再定義できますが、シンボルをロードする必要があります。つまり、PostgreSQLAdapter クラスが存在する必要があります。そのシンボルをロードするのに最も近いのはconfig/environment.rbafterですinitialize!が、そのシンボルをロードするのに十分なスタックの深さではありませんでした。

既にシンボルが読み込まれている ActiveRecord コードの外側の場所を見つけ、そのメソッドを編集できる場合は、次のコードをそこに挿入します。

class ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::StatementPool
  def reconnect!
    clear_cache!
    ActiveRecord::Base.establish_connection
  end
end

さらに、実際に呼び出すのは少しやり過ぎestablish_connectionです。オーバーヘッドを回避するために、そのメソッド内の重要なものを呼び出すことができる場合があります。

これが役に立ったかどうか、また何か進展があったかどうかをお知らせください。

于 2012-11-01T14:04:40.007 に答える
0

あなたが求めていることを正確に行う方法はわかりませんが、別の「プロセス」の提案があります。簡単なスクリプトを設定して、製品エンジニアがすべてのアプリケーションを簡単に停止および開始できるようにします。

製品エンジニアがすべてのアプリケーションを停止および開始するために使用できる一連のcapistranoレシピ(または他のスクリプト)を開発します。通常のRailsアプリの場合、実際に行う必要があるのはメンテナンスページを配置することだけです。これにより、nginxまたはapacheは、Railsインスタンスにリクエストを転送する代わりにそのページを提供します。理想的には、Railsワーカーはリクエストの取得を停止し、dbがダウンし、dbがアップし、次にメンテナンスページが削除され、ワー​​カーが再びリクエストを取得します。データベースがしばらくの間なくなったことに気付くことはありません。

バックグラウンドワーカーの場合、キューが空で空のままでない限り、スクリプトによって実際に停止および開始する必要がある場合があります。スケジュールされたレーキタスクまたは他のスケジュールされたジョブは、データベースに依存し、データベースがダウンしているときに実行されると失敗する可能性があります。したがって、通常はデータベースのメンテナンスを行うときに、ウィンドウの外で実行するようにスケジュールすることをお勧めします。

製品エンジニアがスクリプトの実行(!)を好まない場合は、スクリプトを簡単に実行できるように、優れたWebインターフェイスを設定できます。これは、データベース接続エラーを処理するだけでなく、組織内のより多くの人々がアプリの停止や開始などの基本的なことを処理できるようになるため、おそらく役立つでしょう。

于 2012-11-01T13:17:24.133 に答える
0

この種のイベントを監視するには、外部ツール/スクリプトを使用することをお勧めします。Activerecord の再接続は、データベースが特定のアイドル時間の後に接続を強制終了したときに機能し、特定の時間の失敗後にあきらめます。だからあなたの場合は役に立ちません。

データベースのステータスを監視するには、独自のスクリプトを作成する必要があると思います。しばらくして戻ってきた場合は、Rails アプリを再起動してください。

その上、とにかく、サーバーのメモリと CPU とディスクの使用状況、サーバーの負荷、データベースの状態、一連のものなど、これらの監視が必要になります。わずかにカスタマイズされた監視ルールをもう 1 つだけ追加します。

于 2012-11-11T15:53:14.723 に答える
0

救助をどこかに挿入する

rescue ActiveRecord::StatementInvalid: ActiveRecord::JDBCError
  ActiveRecord::Base::establish_connection
  retry

しかしここで?私は知らない

また、ApplicationController でレスキューを使用することもできます。ただし、これは失敗したアクションを再試行しないため、エラー テンプレートもレンダリングする必要があります。

rescue_from ActiveRecord::StatementInvalid: ActiveRecord::JDBCError do
  ActiveRecord::Base::establish_connection
  render 'errors/error', :status => 500
end
于 2012-09-26T11:48:41.830 に答える