0

たまたま Joe Armstrong の論文を読んだだけで、Erlang についての予備知識はあまりありません。あるメッセージの配信確認が届かなかったらどうなるのだろうか。送信側のアクターは何をしますか? メッセージをもう一度送信しますか?これにより、同じメッセージをもう一度受信したときに、受信者のアクターが混乱する可能性があります。そのレシートが受信されなかったことを伝えることができなければならないため、2 番目のメッセージは無効になります。

この種の問題は、メッセージ配信がトランザクションではない解決策から常に遠ざかっていました。私は答えを知っていると思います: 送信側のアクターは、監督側のアクターに、適切な時間内にレシートを取得できなかった場合、何かが間違っているに違いないと伝え、スーパーバイザーに何らかのアクション (関与するアクターの再起動など) を実行させます。これは正しいです?理論的に無限のメッセージ送信が発生しない解決策は他にありません。

答えてくれてありがとう、オリバー

4

1 に答える 1

2

Erlang では、メッセージの送信者は通常、送信直後にそれを忘れて仕事を続けます。アプリケーションがメッセージ受信の確認を必要とする場合、独自のプロトコルを作成する (または既存のものを使用する) 必要があります。それには多くの正当な理由があります。

1 つは、ほとんどの場合、このハンドシェイクを行う必要がないことです。メッセージが無視されるより高いリスクは、受信プロセスが存在しないか、その間に終了したことです。この場合、送信者は興味深いことを行う機会がほとんどありません。

また、ハンドシェイクはブロッキング アクションであるため、パフォーマンスに影響があり、デッドロックのリスクがあります。

承認もメッセージである必要がありますが、これは承認されるべきではありません。そうしないと、メッセージの終わりのないループが作成されます。アプリケーションだけが何をすべきかを知ることができ (たとえば、確認応答付きの送信を使用するかどうかなど)、この種の関数を作成する (またはそれを実装する動作を使用する) のは非常に簡単です。例えば:

send_with_ack(To,Mess,TimeOut,Ack) ->
    Ref = make_ref(),
    To ! {Mess,self(),Ref},
    receive
        {Ack,Ref} -> Ack
    after Timeout ->
        {error,timeout}
    end.



receiving_process() ->
    ...
     receive
        {Pattern_matching_Mess,From,Ref} ->
            do_something(),
            From ! {Ack,Ref}, %% Ack for this kind of message is known by the receiver
            do_somethingelse();
        Mess1 -> do_otherthing()
    end,
    ...

少しの作業で、メッセージ配信の調査を新しいプロセス (ブロック チェックではなく) に委譲し、リンクされたプロセスを使用して、タイムアウトに達した場合に送信者を強制的にクラッシュさせることさえ可能です。

于 2013-07-05T12:35:58.800 に答える