开发RpcProvider的发布服务(NotifyService)

1.发布服务过程

目前完成了mprpc框架项目中的以上的功能。

作为rpcprovider的使用者,也就是rpc方法的发布方

main函数如下:

首先我们init调用框架的init,然后启动一个provider,然后向provider上注册服务对象方法,即userservice的login方法,当做一个可以远程调用的rpc方法,然后启动run,run相当于是一个网络服务器。
首先,如果远端有RPC请求的话,RpcProvider的网络模块(muduo)会帮助我们去接收数据,就是接收一个RPC请求,RPC请求里面有函数名,函数参数。RpcProvider先把这个请求上报到LoginRequest。我们作为用户,不管底层是怎么进行网络收发(muduo库完成),不管怎么把网络上的字节流反序列化成具体的LoginRequest的数据(protobuf完成),我们只管最后去使用就可以了。

执行对应方法,最后,我们又把响应的结果送给protobuf,RpcProvider首先通过protobuf进行对响应的结果 序列化,然后通过muduo库发送出去。

所以,接下去我们要完成:框架的RpcProvider从网络上接收一个RPC调用请求时,他怎么知道要调用应用程序的哪个服务对象的哪个RPC方法呢?

当远端发送来一个请求,根据一些信息,由框架调用对应方法,定位到需要调用的服务对象的服务方法,相当于一个回调操作。

我们将要实现NotifyService的:
需要生成一张表,记录服务对象和其发布的所有服务方法。
比如说:UserService 发布了Login , Register等方法
FriendService发布了AddFriend,DelFriend,GetFriendList等方法

由一个表记录这些信息,当远端有一个rpc请求过来,rpcprovider就可以在这个表里查一查,需要调用哪个对象的哪个方法,然后就会帮我们去调用,调用后,我们就会看到对应方法被框架调用,就会去执行我们写好的响应操作。


使用protobuf的好处:这些Service都是继承了protobuf的Service类,方法都是继承protobuf的Method类。
而且,我们用户不知道什么时候调用Login,框架才知道,有人请求,框架才调用,因为我们是作为服务方。

当远端有RPC有请求过来时,RpcProvider就可以在这张表查调用的是哪个对象的哪个方法,它就去调用了。

开发RpcProvider的发布服务NotifyService

GetDescriptor方法用于获取一个服务的描述,服务名字、对象、服务对象里面有哪些方法

2. rpcprovider.h

#pragma once
#include "google/protobuf/service.h"
#include <muduo/net/TcpServer.h>
#include <muduo/net/EventLoop.h>
#include <muduo/net/InetAddress.h>
#include <muduo/net/TcpConnection.h>
#include <string>
#include <functional>
#include <google/protobuf/descriptor.h>
#include <unordered_map>


//框架提供的专门发布rpc服务的网络对象类
class RpcProvider
{
public:
    //这里是框架提供给外部使用的,可以发布rpc方法的函数接口
    void NotifyService(google::protobuf::Service* service);//具体的服务对象类是从Service类继承而来
    //框架是可以接收各种RPC服务的,不能依赖具体的某一个业务。 
    //基类指针指向子对象 

    //启动rpc服务节点,开始提供rpc远程网络调用服务
    void Run();

private:
    //组合EventLoop
    muduo::net::EventLoop m_eventLoop;

    //service服务类型信息
    struct ServiceInfo
    {
        google::protobuf::Service* m_service;//保存服务对象
        std::unordered_map<std::string,const google::protobuf::MethodDescriptor*> m_methodMap;//保存服务方法
    };
    //存储注册成功的服务对象和其服务方法的所有信息
    std::unordered_map<std::string,ServiceInfo> m_serviceMap;
    
    //新的socket连接回调
    void OnConnection(const muduo::net::TcpConnectionPtr&);
    //已建立连接用户的读写事件回调
    void OnMessage(const muduo::net::TcpConnectionPtr&,muduo::net::Buffer*,muduo::Timestamp);
};

3.rpcprovider.cc

#include "rpcprovider.h"
#include "mprpcapplication.h"


/*
service_name=> service描述(一个服务由一个服务名字对应)
                    =》 service*  记录服务对象
                    method_name => method方法对象
json:存储键值对,基于文本存储;数据有对应的键值
protobuf:基于二进制存储,存储效率更高;紧密存储,不携带除数据外的任何信息,整体来说protobuf存储效率更高,占用的带宽更少,同样带宽传输的数据量更大
            不仅可以提供类型的序列化和反序列化,还提供了service rpc方法的描述
*/
//这里是框架提供给外部使用的,可以发布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;i<methodCnt;++i)
    {
        //获取了服务对象指定下标的服务方法的描述(抽象描述) UserService Login
        const 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});
    
}

// 启动rpc服务节点,开始提供rpc远程网络调用服务
void RpcProvider::Run()
{
    std::string ip=MprpcApplication::GetInstance().GetConfig().Load("rpcserverip");
    uint16_t port=atoi(MprpcApplication::GetInstance().GetConfig().Load("rpcserverport").c_str());
    muduo::net::InetAddress address(ip,port);

    //创建TcpServer对象
    muduo::net::TcpServer server(&m_eventLoop,address,"RpcProvider");

    //绑定连接回调和消息读写回调方法 ,muduo库的好处是:分离了网络代码和业务代码
    server.setConnectionCallback(std::bind(&RpcProvider::OnConnection, this, std::placeholders::_1));//预留1个参数std::placeholders::_1
    server.setMessageCallback(std::bind(&RpcProvider::OnMessage, this, std::placeholders::_1, 
            std::placeholders::_2, std::placeholders::_3));//预留3个参数std::placeholders::_1,2,3

    //设置muduo库的线程数量
    server.setThreadNum(4);

    std::cout<<"RpcProvider start service at ip:"<<ip<<"port:"<<port<<std::endl;

    //启动网络服务
    server.start();
    m_eventLoop.loop();
}

//新的socket连接回调
void RpcProvider::OnConnection(const muduo::net::TcpConnectionPtr&)
{

}

// 已建立连接用户的读写事件回调
void RpcProvider::OnMessage(const muduo::net::TcpConnectionPtr&,muduo::net::Buffer*,muduo::Timestamp)
{

}

protobuf提供了serviceRPC方法的描述,service类,method类,从抽象的层面描述服务对象,服务方法,到时候,由底层就直接可以用上层的服务方法了。notifyservice就是发布rpc服务的站点

  • 43
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值