2

私は現在、Erlang をそれなりのペースで学んでいますが、スーパーバイザと一緒に gen_server について質問があります。gen_server プロセスがクラッシュし、結果としてスーパーバイザーによって再起動された場合、プロセスは新しい pid を受け取ります。では、他のプロセスがそのプロセスを Pid で参照したい場合はどうすればよいでしょうか? これらのプロセスでPidを「更新」するための良い慣用的な方法は何ですか?

いくつかの実用的なアプリケーションの演習として、クライアントが任意のキーでロックを要求できるロック サーバーを作成しています。理想的には、特定のロックのロックと解放を別々のプロセスに処理させたいと考えています。これは、gen_server でタイムアウト引数を使用して、N 時間後に誰もプロセスを要求しなかった場合にプロセスを終了できるという考えです。関連するロックはメモリに残ります。これで、ロック名をロック プロセスにマップするディレクトリ プロセスが作成されました。ロック プロセスが終了すると、ディレクトリからロックが削除されます。

私の懸念は、ロック プロセスの終了中にクライアントがロックを要求した場合の処理​​方法です。まだシャットダウンしていないため、pid が生きていることをスニッフィングしても機能しません。ロック プロセスは、ディレクトリから削除する句にまだ達していません。

これを処理するより良い方法はありますか?

編集

現在、2 つの gen_servers があります。LockName -> Lock Process から ETS テーブルを維持する「ディレクトリ」と、start_child を使用して監視ツリーに動的に追加される「ロック サーバー」です。理想的には、各ロックサーバーがクライアントとの対話を直接処理することを望んでいますが、プロセスがクラッシュしているときに呼び出しまたはキャストで取得/解放の要求が発行されるシナリオについて心配しています (したがって、応答しません)メッセージに)。

{local} または {global} で始まるのは、N 個の数が存在する可能性があるため機能しません。

4

3 に答える 3

5

秘訣は、プロセスに名前を付け、pid で参照しないことです。通常、実行可能なオプションは 3 つあります。

  • 登録された名前を使用します。これが andreypopp の提案です。サーバーは登録名で参照します。ローカルに登録された名前はアトムである必要があるため、多少制限される場合があります。グローバルに登録された名前にはこの制限がなく、任意の用語を登録できます。

  • スーパーバイザは Pid を知っています。それを聞いてください。Supervisor Pid をプロセスに渡す必要があります。

  • または、gproc アプリケーション ( http://github.comにあります) を使用します。これにより、一般的なプロセス レジストリを作成できます。ETS で作成することもできますが、自分で実装するのではなく、適切なコードを盗むことができます。

すべてのプロセスが同じ監視ツリーの一部である場合、pid を使用できます。したがって、そのうちの1人の死は、他の人の死を意味します。したがって、Pid のリサイクルは重要ではありません。

于 2010-11-14T22:24:26.313 に答える
4

pid で gen_server プロセスを参照しないでください。

gen_server:call/2またはgen_server:call/3関数を介して gen_server に API を提供する必要があります。それらはServerRef最初の引数として受け入れられますName | {Name,Node} | {global,GlobalName} | pid()。したがって、API は次のようになります。

lock(Key) ->
  gen_server:call(?MODULE, {lock, Key}).
release(Key) ->
  gen_server:call(?MODULE, {release, Key}).

この API は gen_server と同じモジュールで定義されていることに注意してください。次のようなものでサーバーを起動すると仮定します。

gen_server:start_link({local, ?MODULE}, ?MODULE, [], [])

したがって、API メソッドは pid ではなくサーバー名でサーバーを検索できます。これは?MODULE.

詳細については、gen_server ドキュメントを参照してください。

于 2010-11-14T20:55:39.617 に答える
1

「erlang:monitor/demonitor」API を使用すると、「lock_server」プロセスの使用を完全に回避できます。

クライアントがロックを要求すると、ロックを発行し、クライアントで erlang:monitor を実行します。これにより、モニター参照が返されます。その後、この参照をロックとともに保存できます。クライアントが停止したときにディレクトリサーバーに通知されること..クライアントにタイムアウトを実装できます。

これは私が最近書いたコードの抜粋です.. https://github.com/xslogic/phoebus/blob/master/src/table_manager.erl

基本的に、table_manager は特定のテーブル リソースのロックをクライアントに発行するプロセスです。クライアントが停止すると、テーブルはプールに返されます。

于 2010-11-15T08:14:03.807 に答える