5

現在の状況: N 個の遅延ジョブ ワーカーを含む Rails アプリがあります。マシンに SSH リクエストを送信するときはいつでも、ワーカー用のタスクを作成します。ワーカーは次のようなことを行います:

Net:SSH.start(hostname, username, :password => pass) do |ssh|
  ssh.exec!(command)
end

時々、50 個のタスクを 1 つずつ、または 5 ~ 10 分以内に実行するように作成します。この場合、各タスクは個別の接続を開きますが、これは効果的ではなく、接続が多すぎるためにターゲット サーバーによってブロックされることがあります。

私が欲しいもの:どこかに保存され、各ワーカーによって再利用される接続を開きました。各ワーカーが何らかの方法で接続を取得してから実行するように

ssh.exec!(command)

私が試したこと

  • ファイル/データベース/キャッシュに接続を保存することは、シリアル化できないため不可能に見えます
  • 初期化子の下でインスタンス化されたグローバル変数を持つシングルトン クラスを使用しようとしました。ただし、クラス オブジェクトはワーカーごとに異なります (後で、グローバル変数をオプションにできないことがわかりました)。

それを解決する方法はありますか?他のアイデアはありますか?ありがとう!!

4

1 に答える 1

3

最初にいくつかの基本事項を説明します。1 つの SSH 接続の中核は、リモート マシンへの低レベル ソケット接続です。プロセス間でソケットを (簡単に) 共有することはできません。したがって、複数のプロセスで実行されるものは、同じ SSH 接続を共有できません。

次に、現在のセットアップのどの部分が個別のプロセスで実行されているかを知る必要があります。得られるものは次のとおりです。

  1. ほとんどの場合、Rails はプロセス ベースです。個別の Web リクエストは個別のプロセスで実行されます。そのため、Rails アプリに SSH 接続を保存することは、信頼できるソリューションではありません。

  2. 私の知る限り、遅延ジョブもプロセスベースです。マスター プロセスはスレーブ プロセスを起動して、各ジョブを処理します。したがって、DJ もこの目的では機能しません。

必要なのは、SSH セッションを保存し、リモート SSH マシンの 1 つで実行する必要があるコマンドである着信メッセージを待機するマスター プロセスです。

個人的には、このタスクを処理する単純なスレッド化された Ruby デーモン プロセスを自分でコーディングするだけです。ソケット プログラミングを直接処理したくない場合は、EventMachineのようなものを使用して通信と処理を処理できます。

EventMachine やソケット プログラミングに慣れていない場合は、クライアントとサーバーを作成するために、 RabbitMQZeroMQなどのメッセージング システムを調べることができます。

ActiveMessagingと呼ばれるRails用のものも見つけましたが、そのプロジェクトがどれほど最新で機能しているかはわかりません。

しかし、私が言ったように、最も単純な実装は、バックグラウンドで実行され、開いている SSH 接続を追跡し、Rails アプリからのコマンドをリッスンするソケット デーモン プロセスだと思います。

このようなものを実装する場合も、セキュリティの考慮事項を忘れずに考慮してください。そうしないと、デーモン プロセスを介して、すべてのリモート マシンへの SSH アクセスを誰にでも簡単に与えることができます。

編集

さらに単純なアイデア:

デーモン プロセスに、Rails アプリのデータベース テーブルから定期的にコマンドを読み取らせるだけです。次に、このデーモンは、この「ジョブ キュー」テーブルで見つけた内容に基づいて、これらのコマンドを実行できます。この方法では、ソケット通信をまったく処理する必要はありませんが、このソリューションはポーリング ソリューションであるという欠点があります。

于 2013-12-13T21:35:27.943 に答える