小编Whi*_*ord的帖子

grpc c ++中的异步模型

我的团队正在设计一个具有微服务架构的可扩展解决方案,并计划将gRPC用作层之间的传输通信.我们决定使用async grpc模型.如果我扩展RPC方法的数量,示例(greeter_async_server.cc)提供的设计似乎不可行,因为那时我将不得不为每个RPC方法创建一个新类,并HandleRpcs()像这样创建它们的对象. Pastebin(简短示例代码).

   void HandleRpcs() {
            new CallDataForRPC1(&service_, cq_.get());
            new CallDataForRPC2(&service_, cq_.get());
            new CallDataForRPC3(&service, cq_.get());
            // so on...
    }
Run Code Online (Sandbox Code Playgroud)

它将被硬编码,所有的灵活性都将丢失.

我有大约300-400个RPC方法实现,并且当我必须处理超过100K RPC请求/秒时,具有300-400个类将是麻烦且低效的,并且该解决方案是非常糟糕的设计.我不能承受在每个请求上以这种方式创建对象的开销.有人可以为我提供一个解决方法.async grpc c++可以像它的同步伴侣一样简单吗?

编辑:赞成使情况更加清晰,对于那些可能正在努力掌握这个异步示例流程的人,我写的是我到目前为止所理解的内容,如果在某处出错,请让我纠正.

在async grpc中,每次我们必须将unique-tag与completion-queue绑定,这样当我们轮询时,服务器可以在客户端命中特定RPC时将其返回给我们,并且我们从返回的内容中推断有关呼叫类型的唯一标记.

service_->RequestRPC2(&ctx_, &request_, &responder_, cq_, cq_,this);这里我们使用当前对象的地址作为唯一标记.这就像在完成队列上注册我们的RPC调用一样.然后我们向下调查HandleRPCs()以查看客户端是否命中RPC,如果是,则cq_->Next(&tag, &OK)填充标记.轮询代码段:

while (true) {
          GPR_ASSERT(cq_->Next(&tag, &ok));
          GPR_ASSERT(ok);
          static_cast<CallData*>(tag)->Proceed();
        }
Run Code Online (Sandbox Code Playgroud)

因为,我们在队列中注册的unique-tag是CallData对象的地址,所以我们可以调用Proceed().这对于一个内部逻辑的RPC来说很好Proceed().但是每次我们将所有这些都放在CallData中时,有了更多的RPC,那么在轮询时,我们将调用唯一一个Proceed()包含逻辑的(例如)RPC1(postgres调用),RPC2(mongodb调用),.等等.这就像在一个函数中编写我的所有程序.因此,为了避免这种情况,我使用了一个GenericCallData带有virtual void Proceed()和派生类的类,每个RPC有一个类,它们自己的逻辑Proceed().这是一个有效的解决方案,但我想避免编写许多类.

我尝试的另一个解决方案是将所有RPC函数逻辑proceed()保留在自己的函数中并保持全局std::map<long, std::function</*some params*/>>.因此,每当我将具有unique-tag的RPC注册到队列中时,我将其相应的逻辑函数(我肯定会硬编码到语句中并绑定所需的所有参数),然后将unique-tag作为键存储.在轮询时,当我得到它时,我&tag在地图中查找此键并调用相应的已保存函数.现在,还有一个障碍,我必须在函数逻辑中执行此操作: …

c++ asynchronous c++11 microservices grpc

7
推荐指数
1
解决办法
2553
查看次数

标签 统计

asynchronous ×1

c++ ×1

c++11 ×1

grpc ×1

microservices ×1