9

OTP スーパーバイザーの動作を使用して、子プロセスを監視および再起動しています。ただし、子供が死亡したときは、クラッシュ前と同じ状態で再起動したいと考えています。

独自のカスタム スーパーバイザを記述した場合、{EXIT,Pid,Reason} メッセージを受け取ってそれに基づいて行動することができます。ただし、OTP スーパーバイザーの動作を使用する場合、それはすべて OTP によって管理され、私はそれを制御できません。私が実装する唯一のコールバック関数は init です。

このような場合の標準的なアプローチはありますか? otp スーパーバイザーによって動的に再起動される子の状態をカスタマイズする方法は? OTPを使用して終了プロセスのPidを取得するには? または、終了直前の子の状態を取得して、子をクラッシュ前と同じ状態に戻すことは可能でしょうか?

4

3 に答える 3

2

おそらく同じ状態で再起動することはお勧めできません。おそらく誤った状態が原因でプロセスがクラッシュし、同じ状態で再起動すると再びクラッシュします。ただし、これが必要な場合は、外部リソースを使用して保持します (ets や mnesia など)。

于 2012-12-01T14:53:55.810 に答える
0

OTP スーパーバイザの動作のこの種のカスタマイズは、簡単には実行できないと思います。OTP スーパーバイザの設計方法により、いくつかの厳密な設計慣行に従う必要があります。この場合の最も重要なことは、スーパーバイザーは、異常終了の場合に子を監視して再起動すること以外に何もすべきではないということです。スーパーバイザにバグを導入しないように、スーパーバイザにロジックを追加しないでください。これは、スーパーバイザ ツリーとフォールト トレランスの重要な部分です。

子が死亡したとき、クラッシュ前と同じ状態で再起動したい - これは一般的に悪い習慣である.確実に問題を起こす

このような場合の標準的なアプローチはありますか? スーパーバイザー内の子の状態をカスタマイズして再起動することは、スーパーバイザーの優れた設計慣行に反します。したがって、この種のタスクは通常、別のプロセスを導入するなど、別のプロセスを導入することによって行われます。たとえば、gen_server はスーパーバイザー (supervisor:start_child) を介して子を開始し、すべてのプロセスでモニターを維持します。この追加プロセスにより、新しい子を開始する前に必要なカスタマイズを行うことができます。

OTPを使用して終了プロセスのPidを取得するには? - Supervisor:start_child を介して子を開始する追加のプロセスでは、それらを監視してから DOWN メッセージを聞くことができます。たとえば、gen_server の場合、次のように handle_info 関数を使用します。

handle_info({'DOWN', Ref, process, _Pid, _}, S) -> 
    handle_down_worker(Ref, _Pid, S).

または、終了直前の子の状態を取得して、子をクラッシュ前と同じ状態に戻すことは可能でしょうか? - 間違っていたら訂正してください。Erlang では、「DOWN」メッセージとともに、終了直前に子プロセスの状態を送信することはできないと思います。それが可能であれば、{DOWN, Pid, Reason, State} のようなメッセージを処理し、同じ状態またはその一部でプロセスを再起動できます。しかし、私は考えています..たとえば exit(Pid, kill) で殺された突然死にかけている子供の状態をどのように保存できますか? 私はそれが可能であろうとは思わない.

于 2012-12-01T15:37:23.677 に答える
0

あなたが何をしているのかについての詳細を知らなくても、次のような世界を想像することができます:

  1. スーパーバイザは ETS テーブルを作成し、テーブル識別子を各子に渡します
  2. 子プロセスが開始し、子の関連する属性に基づいて、ETS テーブルを参照して、ロードする状態を探します。
  3. 子の状態が変化するたびに、ETS テーブルに書き込みます

したがって、Cobol の 12 の部族を表す 12 の子プロセスがある場合、それぞれがその名前を ETS テーブルへのキーとして使用して、開始時に前の化身によって残された状態を検索します。そして、各プロセスは、状態が変化するたびにテーブルを更新します (再びその名前をキーとして使用します)。

スーパーバイザは、強制終了された子を自動的に再起動し、上記のステップ 2 が子の init メソッドで実行されます。ステップ 3 は、子の handle_call、handle_cast、および handle_info メソッドで処理されます (プロセスの性質についていくつかの仮定を立てています)。必要に応じて兄弟を再起動することもできる、スーパーバイザーを介して利用可能な再起動戦略がいくつかあります。

これがあなたにいくつかの考えを与えることを願っています。

于 2012-11-30T04:31:27.580 に答える