C++实现RPC分布式网络通信框架(五)-------本地服务如何注册为RPC服务

到目前为止,我们的理论知识基本足够,当开始编码阶段时,我们第一个要考虑的问题就是如何将一个本地的方法注册成RPC服务方法,从而被远程调用。

一、在proto文件中添加服务

因为全局使用了protobuf作为数据的序列化和反序列化工具,所以需要先在proto文件中定义以下信息:

syntax ="proto3";//定义proto的最低版本
package RPC;//定义生成的namespace
option cc_generic_services=true;//指定将service也生成为类

message ResultCode//消息类型
{
    
    
    int32 errcode=1;
    bytes errmsg=2;
}

message LoginRequest
{
    
    
    bytes name=1;
    bytes pwd=2;
}

message LoginResponse
{
    
    
    ResultCode result=1;
    bool success=2;
}

service UserServiceRpc//定义服务类型,
{
    
    
    rpc Login(LoginRequest)returns(LoginResponse);
}

在proto文件中我们使用了message和service两个关键词组,在编译proto文件时会将他们对应的内容都生成为相应的类,例如:UserService原来是一个本地服务,提供了进程内的本地方法:Login(),在proto文件中需要先在service类中注册该方法(要在proto文件中加上option cc_generic_services=true以将service下的方法生成为C++类的代码)。然后对proto文件进行编译生成后会生成对应的.pb.h和.pb.cc文件,其中会将proto文件注册的service直接生成为对应的类。

proto文件编译指令:protoc -user.proto --cpp_out=./

可以打开对应的user.pb.h文件查看是否生成了对应的类和方法:
在这里插入图片描述
可以看到service已经生成了类,而他对应的Login方法也已经生成了虚函数(生成虚函数的作用下边再说)。

二、注册为RPC方法

在我们要使用注册方法的文件中包含生成的.pb.h文件,书写新的service类,这个新的类需要继承proto文件生成的基类UserServiceRpc,对基类虚函数进行重写,即可将自己写的方法注册为RPC的方法:

class UserService:public RPC::UserServiceRpc
{
    
    
public:
    //本地方法,模拟做本地业务
    bool Login(std::string name,std::string pwd);
    
    //重写的Login方法,用于接收、处理和返回本地业务对应数据
    void Login(::google::protobuf::RpcController* controller,
                       const ::RPC::LoginRequest* request,
                       ::RPC::LoginResponse* response,
                       ::google::protobuf::Closure* done);
};

Login方法参数:

(1)::google::protobuf::RpcController* controller:此参数会携带一些其他的信息,用于做RPC远程方法的其他控制;
(2)::RPC::LoginRequest* request:就是RPC远程调用的请求参数;
(3)::RPC::LoginResponse* response:RPC远程调用完成后此参数用于返回结束后的数据;
(4)::google::protobuf::Closure* done:执行回调操作,用于执行响应对象数据的序列化和网络发送。

三、调用本地服务

在调用本地服务前我们先看下上面两个方法的实现

class UserService:public RPC::UserServiceRpc
{
    
    
public:
    //登入系统的方法
    bool Login(std::string name,std::string pwd)
    {
    
    
        std::cout<<"doing local service:Login"<<std::endl;
        std::cout<<"name:"<<name<<" pwd"<<pwd<<std::endl;
        return true;
    }
    
    void Login(::google::protobuf::RpcController* controller,
                       const ::RPC::LoginRequest* request,
                       ::RPC::LoginResponse* response,
                       ::google::protobuf::Closure* done)
    {
    
    
        //框架给业务上报了请求参数:LoginRequest,应用程序取出相应的已反序列化的数据来做本地业务
        std::string name=request->name();
        std::string pwd=request->pwd();

        //做本地业务
        bool loginresult=Login(name,pwd);

        //把响应写入,包括错误码,错误信息和运行结果
        RPC::ResultCode *Code=response->mutable_result();
        Code->set_errcode(0);
        Code->set_errmsg("");
        response->set_success(loginresult);

        //执行回调操作  执行响应对象数据的序列化和网络发送
        done->Run();
    }
};

Login是重写的虚函数,所以在发起远程请求后会调用这个方法来完成对应的目标请求,其过程为:
1、从LoginRequest获取参数的值;
2、执行本地服务Login,并获取返回值;
3、用上面的返回值填写LoginResponse;
4、一个回调,把LoginResonse发送给发起RPC服务的主机。

重写基类UserServiceRpc的虚函数,以下方法由框架直接调用:
1.caller远程调用者发起远程调用请求Login(LoginRequest) -> muduo -> callee
2.callee发现远程请求调用Login(LoginRequest) -> 交付给重写的方法即可

项目持续更新中……

猜你喜欢

转载自blog.csdn.net/qq_45132647/article/details/107964865