木质家居 技术支持 东莞网站建设自适应式网站模板
web/
2025/9/29 8:32:44/
文章来源:
木质家居 技术支持 东莞网站建设,自适应式网站模板,公司网站建设需要注意什么,qq邮箱网页版RpcProvider#xff08;服务提供者#xff09;实现思路
上一节说到#xff0c;如何将一个本地服务发布成远程服务#xff0c;但没有说明一个rpc框架怎么进行调用的#xff0c;看看上节代码
#include iostream
#include string
#include user.pb.h…RpcProvider服务提供者实现思路
上一节说到如何将一个本地服务发布成远程服务但没有说明一个rpc框架怎么进行调用的看看上节代码
#include iostream
#include string
#include user.pb.h
class UserService : public fixbug::UserServiceRpc //使用rpc服务发布端(rpc服务提供者)
{
public:bool Login(std::string name, std::string pwd){std::coutdoing local service : Login std::endl;std::cout name: name pwd : pwd std::endl;} /*** 重写基类UserServiceRpc的虚函数 下面这些方法都是框架直接调用的* caller Login(LoginRequest) transmit callee* callee Login(LoginRequest) 调用下述的Login方法* */void Login(::google::protobuf::RpcController* controller,const ::fixbug::LoginRequest* request,::fixbug::LoginResponse* response,::google::protobuf::Closure* done){//框架给业务上报了请求参数LoginRequest 应用获取相应数据做本地业务std::string name request-name();std::string pwd request-pwd();//本地业务bool res Login(name, pwd);//把响应写入 包括错误码、错误消息、返回值response-set_success(0);fixbug::ResultCode* rc response-mutable_result();rc-set_errcode(0);rc-set_errmsg();//执行回调操作 执行响应对象数据的序列化和网络发送由框架来完成done-Run();}
};现在实现的发布服务方那么显然Login方法是rpc框架帮我们调用的什么时候调用当rpc客户端通过网络发送rpc调用请求之后这边接收到rpc请求解析请求然后调用发布的服务方法获取服务方法的响应在回传给rpc客户端即完成了一次远程rpc调用过程。 下面一一分析上面步骤的实现思路。 1、 首先RpcProvider肯定是一个服务器接收来自rpc客户端的请求且能在一定程度上承载高并发的需求(考虑多个rpcClient给当前rpcProvider发送rpc调用请求)。显而易见RpcProvider需要一个高性能的网络库来做这些任务那么可以考虑muduo网络库。 2、 网络库有了用什么消息格式–protobuf优势就不赘述了。 消息包含哪些内容一个rpcclient发送请求过来调用一个远程方法那么rpcProvider收到这个请求之后能根据请求所携带的数据自动调用发布的rpc方法那么请求必须包含服务名、方法名、以及参数这样rpcProvider才知道怎么调用。即buffer service_name method_name args。 由于使用的是protobuf二进制消息存储所以涉及到读取这几个参数的问题可以将buffer加个4字节(int不会超过4字节的head_sizehead_size表示service_name和method_name的长度这样可以先读取head_size在根据head_size读取service_namemethod_name。 最后读取args思考一个问题剩下的数据是不是都是args不一定考虑Tcp粘包的情况一次接收到2个rpc调用请求那么args也需要一个长度args_size来表示当前解析的rpc调用的参数长度。 因此这里借助protobuf定义一个消息格式即
message RpcHeader{bytes service_name 1;bytes method_name 2;uint32 args_size 3;
}那么header_size表示是该消息的长度先读header_size在读RpcHeader所包含的字节流最后借助protobuf反序列化出这三个参数那么得到了service_name 、method_name 、args_size。在接着读取args_size长度的字符流数据得到args。最后通过protobuf定义的参数格式反序列化出request。最终所需要的参数都已经拿到了。
3、 那么如何通过上面得到的参数自动调用rpc服务首先得在本地存在这个远程服务前面提到rpc框架来调用Login方法那么 rpcProvider得预先对发布的 rpc方法做一下映射 。
struct ServiceInfo{google::protobuf::Service* m_service; //保存服务对象std::unordered_mapstd::string, const google::protobuf::MethodDescriptor* m_methodMap; //保存服务的所有方法的映射关系};//存储注册成功的服务对象和其服务方法std::unordered_mapstd::string, ServiceInfo m_serviceMap; // service_name --- ServiceInfo例如UserService存在Login 和 Register两个方法 由于UserService继承自UserServiceRpc 那么可以借助protobuf来实现这预先实现这个映射。具体如下
//框架提供给外部使用的可以发布rpc方法的函数接口
void RpcProvider::NotifyService(google::protobuf::Service* service)
{ServiceInfo service_info;//获取服务对象的描述信息const google::protobuf::ServiceDescriptor *pserviceDesc service-GetDescriptor();//获取服务的名字std::string service_name pserviceDesc-name();//获取服务对象service的方法的数量int methodCnt pserviceDesc-method_count();std::cout service_name service_name std::endl;for(int i 0; imethodCnt; i){//获取了服务对象指定下标的服务方法的描述抽象描述 UserService Loginconst google::protobuf::MethodDescriptor *pmethodDesc pserviceDesc-method(i);std::string method_name pmethodDesc-name();service_info.m_methodMap.insert({method_name, pmethodDesc});std::cout method_name: method_name std::endl; }service_info.m_service service;m_serviceMap.insert({service_name, service_info});}RpcProvider可以借助这个方法注册一个rpc服务的站点这样由RpcClient发送过来的rpc调用请求通过muduo和protobuf解析得到上述几个参数之后即可通过映射表调用指定的rpc服务。 即
1、server_name, method_name, args parse(buffer); //解析参数
it m_serviceMap.find(service_name);
method it-second.m_methodMap.find(method_name);
request service-GetRequestPrototype(method).New();
2、request-ParseFromString(args_str) //序列化请求参数
response service-GetResponsePrototype(method).New();
3、service-CallMethod(method, nullptr ,request, response, done); //调用具体的rpc方法
----
4、最终调用LoginLogin(::google::protobuf::RpcController* controller,const ::fixbug::LoginRequest* request,::fixbug::LoginResponse* response,::google::protobuf::Closure* done)
---
5、回调 done()最后服务器调用完指定rpc方法后此时response已填入响应那么需要将respnse借助protobuf反序列化字节流数据再通过muduo网络库发回给rpcClient这就是done回调函数所做的事情。 即
void done(fd, response)
{string response_str;if (response-SerializeToString(response_str)) //将响应进行序列化{//序列化成功后通过网络把rpc方法执行的结果发送给rpc的调用方fd-send(response_str);}fd-shutdown(); //模拟http的短链接服务 由rpcprovider主动断开连接以免占用资源
}到此RpcProvider基本实现。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/83799.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!