2

キーに関連付けられている一時的な gen_servers 状態の保存を処理する方法を知りたいです。

キーをプロセスに関連付けるために、pidstore というプロセスを使用します。Pidstore は最終的にプロセスを開始します。Key と M、F、A を pidstore に渡すと、グローバルでキーが検索され、見つかった場合は pid が返されるか、MFA が適用され ({ok, Pid} が返される必要があります)、Pid がキーに登録されます。グローバルで、Pid を返します。

おそらく巨大な状態の非アクティブな gen_servers が多数ある可能性があります。したがって、handle_info コールバックを設定して状態をデータベースに保存し、プロセスを停止しました。gen_servers はスーパーバイザーでは一時的なものと見なされるため、何かが再び必要になるまで再起動されません。

ここで問題が発生します: {car, 23} を表すプロセスで handle_info を保存するステップで、{car, 23} などのキーを使用してプロセスを呼び出すと、意図したとおりに pid が返されます。プロセスは保存中で、終了していません。したがって、gen_server:call でプロセスを呼び出しますが、プロセスが停止しているため、応答がありません (デフォルトの 5 秒のタイムアウトに達します)。(問題A)

この問題を解決するには、プロセスをグローバルから登録解除し、その状態を保存してから停止します。ただし、登録解除後、保存が完了する前に必要な場合は、新しいプロセスをロードします。このプロセスは、更新されていない値をデータベースにロードする可能性があります。(問題B)

これを再度解決するために、データベースへの読み込みと保存がキューに入れられ、同時に実行できないようにすることができました。これがボトルネックになる可能性があります。(問題C)

私は別の解決策を考えています.私のプロセスは、保存する前に、ビジーであることをpidstoreに伝えることができます. pidstore は、使用中のプロセスのリストを保持し、これらのキーに対するすべての要求に対して「使用中」と応答します。保存が完了すると、pidstore はプロセスによって no_more_busy と通知され、キーを要求されたときに新しいプロセスを開始できます。(古いプロセスが終了していなくても、保存が完了しているため、一人で死ぬのに時間がかかる場合があります)。

これは少し面倒に思えますが、可能性のあるタイムアウトを処理するために gen_server へのすべての呼び出しをラップする代わりに、キーから Pid を取得するためにいくつかの試行を行う方が簡単に感じます。(プロセスが終了しているが、まだグローバルに登録されている場合)。

これらの半分の問題と半分の解決策のすべてについて、私は少し混乱しています。この状況で使用する設計は何ですか、またはこの状況を回避するにはどうすればよいですか?

私のメッセージが判読できることを願っています。英語のエラーについても教えてください。

ありがとうございました

4

2 に答える 2

1

たぶん、でDB部分に保存したいと思うでしょうgen_server:call。これにより、DBへの書き込み中に他の呼び出しが着信するのを防ぐことができます。

一般的に、プロセスレジスタを作成したように聞こえます。ローカルで登録したい場合は、gproc(https://github.com/uwiger/gproc )を調べてください。これは非常に効果的です。gprocを使用すると、上記で説明したことを正確に実行でき、キーを使用してプロセスを登録できます。init関数でgprocに登録し、DBへの書き込み時に登録を解除すれば十分かもしれません。関数でDBに書き込むこともできますterminate

于 2012-04-27T18:00:55.350 に答える
0

今のところ、私は erlang « let it crash » の哲学に固執することにしました。プロセスがシャットダウン中にメッセージを受信した場合、それらのメッセージは応答されず、gen_server:call/* タイムアウトがトリガーされます。

このタイムアウトを適切な場所で処理するのは退屈だと思います。現時点ではどこで処理するかは決めていませんが、これは私のアプリケーションに固有のものであるため、ここでは無意味です。

于 2012-05-02T16:06:45.473 に答える