是否有任何具有信号功能的RPC框架,如DBus?

时间:2017-01-16 13:26:05

标签: ipc thrift dbus grpc capnproto

我们目前正在寻找RPC框架,但遗憾的是我们无法找到任何具有信号功能的框架。我们查看了gRPCApache ThriftCap-n-Proto,发现其中没有一个提供开箱即用的功能,就像DBus一样。值得一提的是,我们需要它作为IPC。此外,我们需要监视另外一个套接字,因此一个用于RPC服务器,另一个用于另一个服务器。在DBus我们可以将它添加到glib的mainloop中。我们的目标RPC必须允许这样做。

P.S。 DBus并不是我们真正需要的,因为我们只需要客户端 - 服务器架构而不是客户端总线守护进程。

P.P.S。关于off-topic - 我在这个问题中看不到什么需要自以为是的答案。答案应该包含事实而不是意见。

1 个答案:

答案 0 :(得分:7)

信号可以通过几种不同的方式在Cap'n Proto之上实现。

对象链

Cap'n Proto RPC调用没有问题需要很长时间才能完成。在同一连接上的其他呼叫可以正常继续,并且您可以一次有许多未完成的呼叫。因此,接收信号的一种策略是在返回之前进行等待信号的呼叫。

许多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.
}

这极大地简化了服务器端的状态管理,因为只要所有客户端都表明它们已经完成,Cap'n Proto就会自动调用每个对象的析构函数(通过破坏客户端引用,又称“删除”它) )。如果客户端断开连接,则会隐式删除其所有引用。

<强>回调

因为Cap'n Proto允许双向RPC调用(客户端 - &gt;服务器和服务器 - >客户端),所以您可以使用回调实现“信号”或发布/订阅机制:

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系统

我上面讨论了Cap'n Proto,因为我是作者,因为它提供了比大多数RPC系统更多的选项。

如果您使用gRPC,您可以使用其“流媒体”功能来支持信号等内容。流式RPC可以随时间返回多个响应。

我不确定Thrift。我最后一次尝试它时,请求必须是FIFO,这意味着长时间运行的RPC是禁止的。然而,那是很久以前的事了,也许从那时起它就发生了变化。