【发布时间】:2020-12-02 02:33:08
【问题描述】:
我已经实现了一个 gRPC 服务器应用程序,多个客户端可以连接到它并调用 RPC。 在客户端断开连接或客户端重新启动的情况下,我想知道哪个客户端断开连接,以便我可以针对该客户端进行一些清理。
同样,如果服务器宕机了,如何通知客户端?
gRPC c++ 堆栈是否向应用程序提供通知/回调?如果不是,那么在任一端处理连接终止的最佳方法是什么?
【问题讨论】:
我已经实现了一个 gRPC 服务器应用程序,多个客户端可以连接到它并调用 RPC。 在客户端断开连接或客户端重新启动的情况下,我想知道哪个客户端断开连接,以便我可以针对该客户端进行一些清理。
同样,如果服务器宕机了,如何通知客户端?
gRPC c++ 堆栈是否向应用程序提供通知/回调?如果不是,那么在任一端处理连接终止的最佳方法是什么?
【问题讨论】:
Tcp 是一个空闲协议,因此为了检测断开的连接,您必须实现某种类型的 ping/pong 和计时器来抛出断开的连接,因此您应该执行以下操作:
在一侧(例如客户端):
在另一端(例如服务器):
除此之外,任何来自读、写的错误(非阻塞错误和喜欢除外)都被视为断开连接。
请注意,ping 和 pong 很重要,因为您可能只在需要时(完成某些工作时)发送其他消息,这可能需要很长时间,因此在此期间您应该 ping 服务器以检查它是否仍与您连接
【讨论】:
gRPC 试图从用户那里抽象出连接管理的细节,因此其中一些细节被有意隐藏了。这意味着 gRPC 服务器会看到传入的 RPC 而不是客户端(尽管您可以在 ServerContext 上调用 peer() 来获取客户端的 uri)。在 RPC 级别,您可以在 ServerContext 上调用 IsCancelled() 以检查 RPC 是否由于某种原因失败(断开连接将被视为失败)。
对于客户端,连接细节再次被抽象出来。在每个新的 RPC 上,如果通道尚未连接,则会进行新的连接尝试。这种方式断开对用户来说是不可见的,除非断开发生在 RPC 正在进行时,在这种情况下,状态详细信息将指向断开。请注意,gRPC 确实在通道上提供了 NotifyOnStateChange() API,以便在更广泛的通道上获得任何状态更改的通知。如果应用程序保证通道使用单个服务器,则 NotifyOnStateChange() 可用于检查传输何时断开。
【讨论】:
NotifyOnStateChange() 仅适用于异步 api 吗?
IsCancelled() 尝试了你的建议,但它似乎在同步 api 上也不起作用。看看这个:gist.github.com/Armmegon/f524ab4765b005f5160beb1e2c0c6d3a