GPRC服务器在处理的第二请求下崩溃

gprc server was crashed on processed second request

本文关键字:请求 崩溃 服务器 处理 GPRC      更新时间:2023-10-16

最近我想在网络后端学习使用GRPC,但是某些问题打破了我的进度

服务器实现

class CGreeterAsyncServerImpl
{
public:
    CGreeterAsyncServerImpl()
        :run_(true){
    }
    ~CGreeterAsyncServerImpl(){
        cq_->Shutdown();
        server_->Shutdown();
    }
    void stop() { run_ = false; }
    void Run(const char* addr) {
        bool ok = false;
        void* tag = nullptr;
        ServerBuilder builder;
        builder.AddListeningPort(addr, grpc::InsecureServerCredentials());
        builder.RegisterService(&service_);
        cq_ = builder.AddCompletionQueue(true);
        server_ = builder.BuildAndStart();
        std::shared_ptr<CMyAsyncRequest> ReqPtr(new CMyAsyncRequest(&service_, cq_.get()));
        while (run_)
        {
            if (!cq_->Next(&tag, &ok)) break;
            if (ok) {
                ReqPtr->Process();
            }
        }
        std::cout << "run exit." << std::endl;
    }
private:
    bool run_;
    Greeter::AsyncService service_;
    std::unique_ptr<Server> server_;
    std::unique_ptr<ServerCompletionQueue> cq_;
};

我的请求实施

class CMyAsyncRequest
{
public:
    CMyAsyncRequest(Greeter::AsyncService* service,ServerCompletionQueue* cq) 
        :service_(service),
        resp_(&ctx_),
        cq_(cq),
        state_(RequestState::RS_PROCESS){
        service_->RequestSayHello(&ctx_, &req_, &resp_, cq_, cq_, (void*)this);
    }
    void Process() {
        switch (state_)
        {
            case CMyAsyncRequest::RS_PROCESS:
            {
                std::string str("hello ");
                str.append(req_.name());
                reply_.set_message(str);
                resp_.Finish(reply_, Status::OK,(void*)this);
                state_ = RequestState::RS_COMPLETED;
            }
            break;
            case CMyAsyncRequest::RS_COMPLETED:
            {
                req_.Clear();
                service_->RequestSayHello(&ctx_, &req_, &resp_, cq_, cq_, (void*)this);
                state_ = RequestState::RS_PROCESS;
            }
            break;
        }
    }
    enum RequestState
    {
        RS_PROCESS,
        RS_COMPLETED
    };
    RequestState state_;
    HelloRequest req_;
    HelloReply reply_;
    ServerContext ctx_;
    ServerCompletionQueue *cq_;
    Greeter::AsyncService* service_;
    ServerAsyncResponseWriter<HelloReply> resp_;
};

最终启动服务器

CGreeterAsyncServerImpl server;
server.Run("0.0.0.0:80");

处理第二个RPC调用时,我的服务器崩溃了并且找不到来自Callstack的任何有用信息

    grpc_server_sample.exe!issue_debug_notification(const wchar_t * const message) Line 125 C++
    grpc_server_sample.exe!__acrt_report_runtime_error(const wchar_t * message) Line 142    C++
    grpc_server_sample.exe!abort() Line 51  C++
    grpc_server_sample.exe!grpc::ServerContext::BeginCompletionOp(grpc::Call * call) Line 161   C++
    grpc_server_sample.exe!grpc::ServerInterface::BaseAsyncRequest::FinalizeResult(void * * tag, bool * status) Line 629    C++
    grpc_server_sample.exe!grpc::ServerInterface::PayloadAsyncRequest<sample::HelloRequest>::FinalizeResult(void * * tag, bool * status) Line 202   C++
    grpc_server_sample.exe!grpc::CompletionQueue::AsyncNextInternal(void * * tag, bool * ok, gpr_timespec deadline) Line 76 C++
    grpc_server_sample.exe!grpc::CompletionQueue::Next(void * * tag, bool * ok) Line 152    C++
    grpc_server_sample.exe!CGreeterAsyncServerImpl::Run(const char * addr) Line 218 C++
    grpc_server_sample.exe!main(int argc, char * * argv) Line 244   C++

我的代码与示例代码不同的是该示例代码在完成一个请求后创建新请求上下文,我想重用下一个请求的请求对象。

示例代码

您需要为每个RPC创建一个新对象作为其数据的容器。ServerContextWriter无法共享RPC之间。