跨语言客户端/服务器的双向RPC选项

3
我正在构思一个项目的想法,其中客户端GUI可以用Python开发,并且GUI可以通过RPC由潜在的任何其他语言的后端驱动。更具体地说,现在我正在客户端使用PyQt,并使用Go作为初始后端。
这是我的目标:
- PyQt客户端 - 角色:视图,控制器 - 单向调用(SIGNAL/SLOT),例如:button.clicked -> RPC.handleSignal - 请求/响应RPC,例如:rowCount = model.rowCount -> RPC.call.model.rowCount - 不可知的后端(在本例中为Go) - 角色:控制器,模型 - 单向调用(发射信号),例如:model.dataChanged -> RPC.emitSignal 我将每个角色称为控制器,因为用户可以在GUI客户端定义信号/槽连接,或者后端可以通过RPC定义自己的信号/槽连接,假设了解客户端上的视图。它完全取决于用户如何设置控制器。
我现在正在查看Thrift,而不是没有IDL的轻量级基本RPC。但是,我的问题主要是是否尝试使用两个.thrift文件来执行Thrift,其中client/server <----> client/server(两个连接),以获得双向功能是否会很混乱?我看到Thrift的好处是IDL,因此我可以特别构建我的接口,并且后端代码只能实现它们想要的部分。
有人对此有解决方案的建议吗?两个Thrift接口?一个Thrift接口,提供服务以让客户端建立第二个简单的套接字以接收来自服务器的单向调用?或者在这里Thrift是否有点过度?虽然后端 -> GUI界面实际上只是单个服务函数,但GUI ->后端可能会扩展一些(modelHandlers,slotHandlers,一般服务器状态查询)。
更多想法:我认为这种模式可以使用任何RPC框架完成,是这样的吗?
- 后端服务器进程启动;侦听端口 - 客户端GUI启动;连接到服务器RPC;侦听新端口;通过RPC调用将端口发送给服务器 - 服务器从客户端接收端口,并将其绑定到第二个RPC连接的端口 - 客户端和服务器具有双向RPC的2个连接
1个回答

2
当您通过TCP(或任何类似的基于连接的协议)连接到服务器时,在连接时您的PC已经选择并监听了一个(伪/相对)随机端口,以便接收服务器的响应。因此,在服务器保持连接并且双方保持连接活动的情况下,您已经拥有了双向连接。因此,从技术上讲,您不需要启动第二个连接。
根据您的RPC系统,它可能会使用TCP,也可能不会具备双向通信(或者说双向通信初始化)。
现在,对于Thrift来说,似乎还没有太多的文档(没有API参考)。但是检查示例代码,它似乎将连接处理抽象化,并仅使用请求/响应通信。因此,在这种情况下,是的,您需要在客户端定义一个端口并告诉服务器,以便服务器可以启动请求/响应通信。
Go本身提供了rpc包,该包专为Go数据而设,因此对您没有帮助。
然而,它也提供了 websocket。尽管最初是针对 web 服务器到 web 浏览器的通信,但它是一个双向协议(毕竟这就是它的目的),可以被任何应用类型使用。虽然在大小/带宽方面可能不太有效率,但它能够完成工作。
我不确定 go 包中实现的状态。Conn 类型确实有一个 origin 字段,但 Conn.Dial 函数示例传递了 http://localhost;我不确定这是否会被替换为可远程访问的 websocket origin。Handler.ServeHTTP 函数提供了一个 http.ResponseWriter,你可能也可以用它来初始化连接。至少这是我要测试的第一件事。

如果您习惯使用定义的数据格式并自己处理网络,另一种选择是使用protobuf。有一个针对 Go 绑定到 Protobuf 的社区项目。然后您可以自己处理 TCP 连接(连接、发送数据、接收数据、保持连接信息等)。

至于其他替代方案,您可以查看社区包页面社区项目页面(尤其是 Go Ajax 和 go-xmlrpc - 尽管这两者目前都非常基础)。


Go protobuf目前不支持rpc,所以我必须为go rpc包编写自己的编码器解码器。因此,您一般建议使用两个连接和thrift或protobuf层的选项?我认为实现单个连接的唯一方法是进行直接套接字连接和多个双向rpc调用。Websocket在这种情况下似乎完全不必要。除非我想得太抽象,让pyqt ui与基于http的服务器通信。但在那种情况下,任何一个这些服务器都可以执行原始tcp。 - jdi
我从这里的评论中再也没有听到任何详细信息,但是时间过得这么久了,我想这可能是我能得到的最好的答案 :-) - jdi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接