对 C++ 对象的并发远程过程调用

Posted

技术标签:

【中文标题】对 C++ 对象的并发远程过程调用【英文标题】:Concurrent Remote Procedure Calls to C++ Object 【发布时间】:2013-07-17 21:53:40 【问题描述】:

我想要一个用 C++ 编写的类作为远程过程调用服务器。

我有一个要解析的大(超过 1 GB)文件,读取参数以实例化对象,然后将其存储在 std::map 中。我希望 RPC 服务器监听来自客户端的调用,获取从客户端传递的参数,在 map 中查找适当的值,进行计算,并将计算的值返回给客户端,我希望它服务并发请求——所以我想让多个线程监听。顺便说一句,地图填充后,它不会改变。请求只会从中读取。

我想用 Python 编写客户端。服务器可以只是一个HTTP服务器,监听POST请求,客户端可以使用urllib发送吗?

我是 C++ 新手,所以我不知道如何编写服务器。谁能给我举一些例子?

【问题讨论】:

为什么选择 C++?您可以简单地编写一个 python 服务器 (***.com/questions/14088294/…)。如果您的计算耗时或在 C++ 中,只需使用 ctypes 包装它 你不能在 Python 中做线程,只能做多处理——所以如果服务器在 Python 中,我就不能拥有我想要的线程映射。 @JohnPeterThompsonGarcés:首先,是的,您可以在 Python 中执行线程。如果您只需要并发请求,那么您就完成了。如果您需要并发 CPU-bound 请求,其中 CPU-bound 代码是您的 C++ 类,只需让您的包装器围绕对该类的调用释放 GIL。虽然我们这样做了,但在进程之间共享 std::map 并不难。 进程之间的任何共享都不需要大量的消息传递吗?我想使用共享内存。你谈到释放 GIL。这听起来很复杂。 您可以跨线程共享地图,就像在 C++ 中一样。对于 GIL,我发现这很有帮助 (docs.python.org/release/1.5.2/api/threads.html) 特别是 - Py_BEGIN_ALLOW_THREADS ...执行一些阻塞 I/O 操作... Py_END_ALLOW_THREADS 【参考方案1】:

也许因素会影响选择。

一种解决方案是使用 fastcgi。

客户端向启用了 fastCGI 的 HTTP 服务器发送 HTTP 请求。 HTP 服务器通过 fastcgi 机制将请求发送到您的 RPC 服务器。 RPC 服务器处理并生成响应,并发送回 http 服务器。 http 服务器将响应发送回您的客户端。

【讨论】:

【参考方案2】:

如果你必须用 C++ 编写服务器,而你不知道如何去做,那么你肯定想使用框架。

那里有很多选择,而 *** 不是就不同选择征求意见的好地方。但是举个例子,JsonRpc-Cpp 让你用大约 10 行代码实现一个 JSON-RPC(通过原始 TCP 或 HTTP)服务器,加上你想要公开的每个 RPC 的一行样板。比从头开始编写服务器要容易得多。

所以,这是一个示例服务器:

#include <cstdlib>
#include <jsonrpc.h>

class Service 
public:
    bool echo(const Json::Value &root, Json::Value &response) 
        response["jsonrpc"] = "2.0";
        response["id"] = root["id"];
        Json::Value result;
        result["params"] = root["params"];
        response["result"] = result;
        return response;
    


int main(int argc, char *argv[]) 
    int port = std::atoi(argv[1]); // add some error handling here...

    Json::Rpc::TcpServer server("127.0.0.1", port);
    Service service;
    server.AddMethod(new Json::Rpc::RpcMethod<Service>(service,
                     &Service::echo, "echo");
    server.Bind(); // add error handling again
    server.Listen();
    while(true) server.WaitMessage(1000);


但是,如果你用 Python 编写服务器,或者使用 WSGI Web 服务器并用 Python 编写服务,然后从 Python 调用 C++ 代码(无论是通过ctypes,还是通过构建一个使用 Cython 或 SIP 之类的包装器)。

这是在 Python 中使用 bjsonrpc 的同一台服务器:

import bjsonrpc

class Service(bjsonrpc.handlers.BaseHandler):
    def echo(self, *args):
        return 'params': args

server = bjsonrpc.createserver(handler_factory = Service)
server.serve()

【讨论】:

以上是关于对 C++ 对象的并发远程过程调用的主要内容,如果未能解决你的问题,请参考以下文章

远程过程调用

来自 Python | 的远程过程调用红宝石 | ... 到 C++

本地调用Feign远程接口

RPC 中的最大并发连接数是多少?

Java远程过程调用基础:构建可自适应的动态代理对象的通用方法

远程过程调用和 MIDL:如何实现具有 [out] 属性的功能?