船長プロトRPCコールが完了するまでに非常に長い時間がかかっても問題はありません。同じ接続上の他のコールは正常に継続でき、一度に多数の未処理コールを持つことができます。したがって、信号を受信するための1つの戦略は、戻る前に信号を待つ呼び出しを行うことです。
他のほとんどのRPCシステムとは異なり、Cap'n Protoはオンザフライで新しいオブジェクトの生成をサポートします。したがって、シグナルのストリームを一連のオブジェクトとして表現することができます。たとえば、次のように
struct MyPayload { ... }
interface MyInterface {
subscribe @0() -> (firstSignal :Signal(MyPayload));
# Subscribe to signals from this interface.
}
interface Signal(Type) {
# One signal in a stream of signals. Has a payload, and lets you
# wait for the next signal.
get @0() -> (value :Type);
# Gets the payload value of this signal. (Returns immediately.)
waitForNext @1() -> (nextSignal :Signal(Type));
# Waits for the next signal in the sequence, returning a new
# `Signal` object representing it.
}
船長プロトが自動的にクライアント側を破壊することによって(とすぐに、すべてのクライアントは、彼らはそれで行われていることを示してきたように、各オブジェクトのデストラクタを呼び出しますので、これは非常にサーバー側で状態管理を簡素化参照、別名「落とす」)。クライアントが切断されると、そのすべての参照が暗黙的に削除されます。
コールバックは
船長プロトが両方向でRPCコールできるので(クライアント - >サーバーとサーバー - >クライアント)を、あなたは「信号」を実装することができますまたはコールバックを用いた機構をパブリッシュ/サブスクライブ:
struct MyPayload { ... }
interface MyInterface {
subscribe @0 (cb :Callback(MyPayload)) -> (handle :Handle);
}
interface Callback(Type) {
call @0 (value :Type);
}
interface Handle {}
クライアントはsubscribe()
を呼び出し、コールバックオブジェクトcb
を渡します。サーバーは、信号があるときはいつでもクライアントにコールバックすることができます。
subscribe()
は、メソッドを持たないオブジェクトであるHandle
を返します。この目的は、クライアントがいつ退会するかを検出することです。クライアントがhandle
をドロップすると、サーバーに通知され(サーバー側オブジェクトのデストラクタが実行されます)、サーバーはコールバックの登録を解除できます。これは、クライアントが切断する場合も処理します。すべてのオブジェクト参照は、切断時に暗黙的に削除されます。
このソリューションは、シンプルさのために、オブジェクト連鎖ソリューションよりもはるかに優れています。しかし、オブジェクト参照が両方向に向いているので、サイクルにつながるという問題があります。クライアントコードの中で、コールバック実装が登録を保持するハンドルを「所有」していないことを確認する必要があります。そうしないと、(接続が終了したときを除いて)決してクリーンアップされません。また、サーバーがコールバックを登録解除するのを待つ間に、ハンドルを破棄した後も短時間コールバックを呼び出すことができるようにする必要があります。これらの問題は、オブジェクト連鎖ソリューションには存在しないため、そのソリューションをより洗練されたものにすることができます。
その他のRPCシステム
それはほとんどのRPCシステムよりも多くのオプションを提供しますので、私は作者だとので、私は上記の船長プロトを議論しました。
gRPCを使用する場合は、「ストリーミング」機能を使用して信号のようなものをサポートできます。ストリーミングRPCは、時間の経過とともに複数の応答を返すことができます。
私はスリフトについてはわかりません。私が最後に試してみたところでは、リクエストはFIFOでなければならず、長時間実行されていたRPCはノー・ノーであった。しかし、これはずっと前のことであり、それ以来変わっていたかもしれません。
最初に信号を受信した後にコールバックの登録を解除したくない場合はどうすればいいですか?どういうわけか、 'Handle'をどこかに置いておくべきですか? –
@VictorPolevoyクライアントは 'Handle'をメモリに残しておく必要があります。ただし、操作全体が特定のライブネットワーク接続に結びついているため、おそらくディスクには保存されません。接続が切断された場合、コールバックは機能しなくなります。クライアントは再接続して新しいコールバックを登録する必要があります。 –
外部からソケットを使用する方法は、以前にソケットから受け取ったデータバッファをcapnpに渡すことで解析できますか? –