网络模块的设计
RpcProvider类的设计:
// 框架提供的专门服务发布rpc服务的网络对象类
class RpcProvider
{
public:
// 启动rpc服务结点,开始提供rpc远程网络调用服务
void Run();
private:
// 组合EventLoop
muduo::net::EventLoop m_eventLoop;
// 新的socket连接回调
void OnConnection(const muduo::net::TcpConnectionPtr&);
// 已建立连接用户的读写事件操作
void OnMessage(const muduo::net::TcpConnectionPtr&, muduo::net::Buffer*, muduo::Timestamp);
};
启动方法的实现
// 启动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");
// 绑定连接回调和消息读写回调方法 分离了网络代码和业务代码
server.setConnectionCallback(std::bind(&RpcProvider::OnConnection, this, std::placeholders::_1));
server.setMessageCallback(std::bind(&RpcProvider::OnMessage, this, std::placeholders::_1,
std::placeholders::_2, std::placeholders::_3));
// 设置muduo库的线程数量
server.setThreadNum(4);
// 显示信息
std::cout << "RpcProvider start service at ip: " << ip << "port: " << port << std::endl;
// 启动网络服务
server.start();
m_eventLoop.loop();
}
那目前实现的功能除了初始化rpc框架和加载配置文件,还设计一个类RpcProvider,实现了框架的网络模块,RpcProvider还需要有提供服务方法:NotifyService()
再来看请求过程:
如果有请求从网络上发送过来
本地的方法会从中得到请求的参数,执行本地服务,然后把响应response填写好,执行回调操作返回。
那么问题就是,当接收到一个rpc调用请求时,如何知道要调用哪个应用程序的哪个rpc方法呢?
首先的思路是,我们需要一个表,来记录当前节点的服务对象和服务方法信息。
NotifyService的实现
由于rpc方法的实现是通过继承Service类的的派生类实现的,所以需要一个参数:
google::protobuf::Service。
然后要设计一个结构体,来记录方法,所需要知道的信息:
service_name -> service描述 -> service* 记录服务对象 -> method_name -> method方法描述
// 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;
NotifyService的实现:
// 这里是框架提供给外部使用的,可以发布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)
{
// 获取了服务对象指定下标的服务方法的描述(抽象描述)
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});
}