使用多线程时的grpc异步服务器核心

时间:2019-07-17 11:33:05

标签: c++ grpc

我有一个grpc异步服务器:一个具有多线程的完整队列。 它将以如下输出为核心:

E0717 18:54:02.635424482   14110 server_cc.cc:677]           Fatal: grpc_call_start_batch returned 8
E0717 18:54:02.635514690   14110 server_cc.cc:678]           ops[0]: SEND_MESSAGE ptr=0x7f3c0815cb60
E0717 18:54:02.635563281   14110 server_cc.cc:678]           ops[1]: SEND_STATUS_FROM_SERVER status=0

当我仅使用一个线程时,它运行良好。如果线程数少,则服务器可以运行更长的时间。

class BaseCallData {
 public:
  BaseCallData(XFRProcessor *processor)
      : processor_(processor), status_(CallStatus::CREATE) {}
  virtual ~BaseCallData() = default;

  void Proceed() {
    if (status_ == CallStatus::CREATE) {
      status_ = CallStatus::PROCESS;
      Request();
    } else if (status_ == CallStatus::PROCESS) {
        NewCallData();

        //TODO
        OnRequest();

        Response();

        status_ = CallStatus::FINISH;
    } else if (status_ == CallStatus::FINISH) {

      req_timer_.timer_->SetSelfEnd("delete");
      delete this;
    } else {
      LOGGER_ERROR(Log::GetLog(), "wrong grpc status");
    }
  }

  protected:
  std::unique_ptr<PrometheusMetricsWrapper> prometheus_metrics_;
 private:
  ...
  enum class CallStatus { CREATE, PROCESS, FINISH };
  CallStatus status_;
};

class DetectCallData : public BaseCallData {
 public:
  DetectCallData(::xfr::XFRService::AsyncService *service, ServerCompletionQueue *cq, XFRProcessor *processor)
      : BaseCallData(processor), p_service_(service), p_cq_(cq), responder_(&ctx_) {
    Proceed();
  }

  void NewCallData() override {
    new DetectCallData(p_service_, p_cq_, GetProcessor());
  }

  void Request() override {
    p_service_->RequestDetect(&ctx_, &request_, &responder_, p_cq_, p_cq_, this);
  }

  void Response() override {
    responder_.Finish(response_, Status::OK, this);
  }

  void OnRequest() override {
    //process
  }
 private:
  ServerContext ctx_;
  ::xfr::XFRService::AsyncService *p_service_;
  ServerCompletionQueue *p_cq_;
  ::xfr::DetectRequest request_;
  ::xfr::DetectResponse response_;
  ...
  ServerAsyncResponseWriter<::xfr::DetectResponse> responder_;
};


class XFRServer final {
 public:
  XFRServer(const XFRServer &) = delete;
  XFRServer &operator=(const XFRServer &) = delete;

  XFRServer() {
    Init();
    builder_.AddListeningPort(address_, InsecureServerCredentials());
    builder_.RegisterService(&service_);
    cq_ = builder_.AddCompletionQueue();
  }

  void Init() {
    ...
  }

  ~XFRServer() {
    server_->Shutdown();
    //document shows that cq should always shutdown after server

    cq_->Shutdown();
  }

  void HandleRpcs(ServerCompletionQueue *cq) {
    new DetectCallData(&service_, cq, detect_processor.get());

    void *tag{nullptr};
    bool ok{false};
    while (true) {
      if (!cq->Next(&tag, &ok)) {
        LOGGER_WARN(Log::GetLog(), "Server stream closed");
        break;
      }

      static_cast<BaseCallData *>(tag)->Proceed();

      if(!ok){
        LOGGER_WARN(Log::GetLog(),"status wrong when tag out from complete queue");
      }
    }
  }

  void run() {
    server_ = builder_.BuildAndStart();
    for (int i=0; i<100; i++) {//!!!!!when set 100 to 1, it works well
      v_threads_.emplace_back(
          std::thread([this] {
            HandleRpcs(cq_.get());
          })
      );
    }
    LOGGER_INFO(Log::GetLog(), "grpc server start working...");
    for (auto &t: v_threads_) {
      t.join();
    }
  }

 private:
  ...
};

}  //namespace grpc
}  // namespace xfr
}  // namespace vision
}  // namespace hobot

#endif //XFR_GRPCSERVER_H

有人可以告诉我如何构建具有多线程的异步服务器吗? 我的代码有什么问题?

0 个答案:

没有答案