2017-01-16 10 views
3

私たちは現在RPCフレームワークを探していますが、残念ながら信号機能を持つものは見つかりませんでした。我々はgRPC,Apache Thrift,Cap-n-Protoを見て、どれもDBusと同じようにそのような機能を提供していないことがわかりました。言及に値するが、我々はIPCとしてそれを必要とする。また、RPCサーバー用と別のサーバー用の1つのソケットを監視する必要があります。 DBusではglibのメインループに追加することができます。私たちのターゲットRPCはこれを許可しなければなりません。DBusのようなシグナル機能を持​​つRPCフレームワークはありますか?

P.S. DBusは本当に必要なものではありません。クライアント・バス・デーモンの代わりにクライアント・サーバー・アーキテクチャだけが必要なためです。

P.P.S. off-topicについて - 私はこの質問の中で、意見のある答えが必要なものは何も見ません。回答には事実は含まれていますが、

答えて

6

信号は、いくつかの異なる方法でCap'n Protoの上に実装できます。オブジェクトの

チェーン

船長プロトRPCコールが完了するまでに非常に長い時間がかかっても問題はありません。同じ接続上の他のコールは正常に継続でき、一度に多数の未処理コールを持つことができます。したがって、信号を受信するための1つの戦略は、戻る前に信号を待つ呼び出しを行うことです。

多くのRPCシステムではハングコールがサポートされていますが、信号のストリームがあり、クライアントがストリーム内の信号ごとにを観測することが重要です。新しい信号が生成されると状況が複雑になりますクライアントがRPCを呼び出して読み取るよりも高速です。クライアントごとにバッファを保持する必要があります。しかし、クライアントが死んでリクエストを停止するとどうなりますか?今すぐあなたはそれをクリアするいくつかの種類のタイムアウトが必要です。

他のほとんどの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はノー・ノーであった。しかし、これはずっと前のことであり、それ以来変わっていたかもしれません。

+0

最初に信号を受信した後にコールバックの登録を解除したくない場合はどうすればいいですか?どういうわけか、 'Handle'をどこかに置いておくべきですか? –

+0

@VictorPolevoyクライアントは 'Handle'をメモリに残しておく必要があります。ただし、操作全体が特定のライブネットワーク接続に結びついているため、おそらくディスクには保存されません。接続が切断された場合、コールバックは機能しなくなります。クライアントは再接続して新しいコールバックを登録する必要があります。 –

+0

外部からソケットを使用する方法は、以前にソケットから受け取ったデータバッファをcapnpに渡すことで解析できますか? –

関連する問題