4

私はまだ erlang/otp の世界に慣れていないので、これはかなり基本的な質問だと思います。それにもかかわらず、次の正しい方法を知りたいです。

現在、トップスーパーバイザーに応募しています。後者は、gen_tcp:accept を呼び出して (スリープ状態で) ワーカーを監視し、受け入れられた接続ごとにプロセスを生成します。注: この質問には、listen() がどこで行われるかは関係ありません。

私の質問は、これらのワーカー (gen_tcp:accept でスリープするワーカー) がシステム メッセージ (シャットダウン、トレースなどを処理する) を処理できるように、otp 設計原則を尊重する正しい方法についてです。私はここで読んだ:http://www.erlang.org/doc/design_principles/spec_proc.html

そう、

  • これに gen_fsm や gen_server などの利用可能な動作の 1 つを使用することは可能ですか? 私の推測では、gen_tcp:accept/1 への呼び出しがブロックされているため、いいえです。受け入れタイムアウトを指定することでそれを行うことはまだ可能ですか? もしそうなら、accept() 呼び出しをどこに置くべきですか?
  • または、上記のリンクの例のように、ゼロからコーディングする必要がありますか (つまり、既存の動作を使用しないでください)。この場合、gen_tcp:accept/1 の代わりに gen_tcp:accept/2 を呼び出す (つまり、タイムアウトを指定する) メイン ループを考え、その直後に受信ブロックをコーディングして、システム メッセージを処理できるようにします。これは正しいですか、受け入れられますか?

前もって感謝します :)

4

3 に答える 3

1

Erlang はイベント駆動型であるため、accept/{1,2} のようにブロックするコードを扱うのは厄介です。

個人的にはgen_server、リスナー用のスーパーバイザーと、受け入れワーカー用の別のスーパーバイザーが必要です。gen_tcp:accept/2ステータスのメッセージを受信するのではなく、受け入れワーカーをタイムアウト ( ) にハンドロールし、効果的にポーリングします (厄介な部分)。

このようにして、ワーカーが死亡した場合、その上のスーパーバイザーによって再起動されます。リスナーが停止すると再起動しますが、そのリスナーに依存するワーカー ツリーとスーパーバイザーを再起動する前ではありません。もちろん、最上位のスーパーバイザーが死亡した場合は、再起動されます。ただし、supervisor:terminate_child/2ツリー上にいる場合は、そのソケットのリスナーとすべてのアクセプターを効果的に無効にすることができます。後で、supervisor:restart_child/2リスナー全体とアクセプター ワーカー プールを再起動できます。

アプリでこれを管理したい場合は、カウボーイが上記を実装しています。http 指向ですが、代わりに使用するプロトコルのカスタム ハンドラーを簡単にサポートします。

于 2012-05-18T20:10:50.687 に答える
1

私は実際に別の質問で答えを見つけました:OTP原則を使用したノンブロッキングTCPサーバーとここhttp://20bits.com/article/erlang-a-generalized-tcp-server

編集:私にとって役に立った具体的な答えは: https://stackoverflow.com/a/6513913/727142

于 2012-05-19T15:40:57.850 に答える
0

https://github.com/alinpopa/qerl/blob/master/src/qerl_conn_listener.erlのような gen_server として作成できます。

ご覧のとおり、このプロセスは tcp の受け入れを行い、他のメッセージを処理しています (例: stop(Pid) -> gen_server:cast(Pid,{close}))。

HTH、アリン

于 2012-05-17T19:51:06.763 に答える