文章目录
前言
这篇文章是建立在JsonRpc:手搓一个高性能Rpc服务(底座篇)的基础上进行封装实现Rpc的应用功能
一、通信调度层
在上篇中,我们在服务端和客户端的抽象层中设置了消息回调函数,因为在Rpc通讯的过程中涉及到大量类型的消息和大量不同的方法,针对于每一种方法和消息类型,我们需要有不同的处理手段
1-1 Dispatcher
- 消息类型的分发
namespace gchrpc
{
class Callback{
public:
using ptr=std::shared_ptr<Callback>;
virtual void onMessage(const BaseConnection::ptr& conn,BaseMessage::ptr& msg)=0;
};
//Success这里的_handler
template<typename T>
class CallbackT:public Callback
{
public:
using ptr=std::shared_ptr<CallbackT<T>>;
using MessageCallBack=std::function<void(const BaseConnection::ptr& conn,std::shared_ptr<T>& msg)>;
//Success
CallbackT(const MessageCallBack& handler):_handler(handler){}
//Success
void onMessage(const BaseConnection::ptr& conn,BaseMessage::ptr& msg)
{
auto it=std::dynamic_pointer_cast<T>(msg);
_handler(conn,it);
}
private:
MessageCallBack _handler;
};
class Dispatcher
{
public:
using ptr=std::shared_ptr<Dispatcher>;
//Success针对于每个消息类型进行自定义回调函数的处理;
template<typename T>//success ////const std::function<void(const BaseConnection::ptr& conn,std::shared_ptr<T>& msg)>
void registerHandler(MType mtype,const typename CallbackT<T>::MessageCallBack& handler)
{
std::unique_lock<std::mutex> lock(_mutex);
auto item=std::make_shared<CallbackT<T>>(handler);
_handlers.insert(std::make_pair(mtype,item));
}
//Success使用CallbackT内置的函数处理相关的connection和basemessage
void OnMessage(const BaseConnection::ptr& conn,BaseMessage::ptr& msg)
{
std::unique_lock<std::mutex> lock(_mutex);
auto it=_handlers.find(msg->mtype());
if(it!=_handlers.end())
{
return it->second->onMessage(conn,msg);
}
ELOG("消息类型错误:%d",(int)msg->mtype());
conn->shutdown();
}
private:
std::mutex _mutex;
std::unordered_map<MType,Callback::ptr> _handlers;
};
}
我们需要对不同的消息类型有不同的处理方法,并且将这些方法存在unordered_map中,等后面需要使用的时候直接从unordered_map中拿出来就可以了,但前提是我们已经注册了这种消息类型的处理方法
1-2 Requestor
- 个体消息的分发
namespace gchrpc
{
namespace client
{
class Requestor
{
public:
using ptr=std::shared_ptr<Requestor>;
using RequestCallBack=std::function<void(const BaseMessage::ptr&)>;
using AsyncResponse=std::future<BaseMessage::ptr>;
struct RequestDescribe{
using ptr=std::shared_ptr<RequestDescribe>;
BaseMessage::ptr request;
RType rtype;
RequestCallBack callback;
std::promise<BaseMessage::ptr> response;
};
//!处理response
//success根据requestdescribe的描述来处理BaseMessage
void onResponse(const BaseConnection::ptr& conn,BaseMessage::ptr msg)
{
std::string rid=msg->rid();
RequestDescribe::ptr rd=GetRequestDescribe(rid);
if(rd==nullptr)
{
ELOG("未找到对应的RequestDescribe");
return;
}
if(rd->rtype==RType::REQ_ASYNC)
{
rd->response.set_value(msg);
}
else if(rd->rtype==RType::REQ_CALLBACK)
{
if(rd->callback)
{
rd->callback(msg);
}
else
{
ELOG("未设置回调函数");
}
}
else
{
ELOG("rd的rtype的类型错误");
}
DeleteRequestDescribe(rid);
}
//!send不处理response,发送Message后将requestdescribe存储在哈希表中
//success非阻塞无调用函数
bool send(const BaseConnection::ptr&conn,const BaseMessage::ptr& msg,AsyncResponse& async_rsp)
{
RequestDescribe::ptr rd=newDescribe(msg,RType::REQ_ASYNC);
if(rd==nullptr)
{
ELOG("创建RequestDescribe失败");
return false;
}
conn->send(msg);
async_rsp=rd->response.get_future();
return true;
}
//success阻塞无调用函数
bool send(const BaseConnection::ptr& conn,const BaseMessage::ptr& msg,BaseMessage::ptr& rep)
{
AsyncResponse AR;
bool ret=send(conn,msg,AR);
if(ret==false)
{
ELOG("发送失败");
return false;
}
rep=AR.get();
return true;
}
//success非阻塞有调用函数
bool send(const BaseConnection::ptr& conn,const BaseMessage::ptr& msg,const RequestCallBack& rc)
{
RequestDescribe::ptr rd=newDescribe(msg,RType::REQ_CALLBACK,rc);
if(rd==nullptr)
{
ELOG("RequestDescribe创建失败");
return false;
}
conn->send(msg);
return true;
}
private:
//success:添加对于request的描述,描述包含promise回复,和唯一标识符rid,和回调函数
RequestDescribe::ptr newDescribe(const BaseMessage::ptr& mp,RType Rtype,
const RequestCallBack& rb=RequestCallBack())
{
std::unique_lock<std::mutex> lock(_mutex);
RequestDescribe::ptr rp=std::make_shared<RequestDescribe>();
rp->rtype=Rtype;
rp->request=mp;
if(rp->rtype==RType::REQ_CALLBACK&&rb)
{
rp->callback=rb;
}
_request_desc.insert(std::make_pair(rp->request->rid(),rp));
return rp;
}
//success用string rid获取一个request描述
RequestDescribe::ptr GetRequestDescribe(const std::string& rid)
{
std::unique_lock<std::mutex> lock(_mutex);
auto it=_request_desc.find(rid);
if(it==_request_desc.end())
{
DLOG("不存在对应的rid:%s",rid.c_str());
return nullptr;
}
return it->second;
}
//success用string rid删除一个request描述
void DeleteRequestDescribe(const std::string& rid)
{
std::unique_lock<std::mutex>lock(_mutex);
_request_desc.erase(rid);
}
std::mutex _mutex;
std::unordered_map<std::string,RequestDescribe::ptr> _request_desc;
};
}
}
这里的requestor负责客户端发送消息并设置当服务端发送回复消息后,处理这条回复的方法,是异步调用还是同步调用还是回调函数处理
因为客户端没发送出去的数据,客户端接收到后都要进行处理,这个处理的规则就在RequestDescribe,当客户端接收到回复的报文后,会比对一下回复的处理方法,在unordered_map中通过rid找到对应的回复处理方法
二、业务功能层:服务注册端
讲解Rpc的业务层,那么我们就需要先讲解Rpc的核心:服务注册功能,在服务注册中,我们记录了两个描述,一个是客户端要发现哪些方法,和服务端提供了哪些方法,那么我们先从服务端开始讲起
2-1 服务端注册管理
class ProviderManager
{
public:
using ptr = std::shared_ptr<ProviderManager>;
//success一个提供者的connection和它所能提供的方法和IP
struct Provider
{
using ptr = std::shared_ptr<Provider>;
std::mutex _mutex;
Address host;
std::vector<std::string> methods;
BaseConnection::ptr conn;
Provider(const BaseConnection::ptr &NewConn, const Address &NewHost) : conn(NewConn), host(NewHost)
{
}
void AppendMethod(const std::string &method)
{
std::unique_lock<std::mutex> lock(_mutex);
methods.push_back(method);
}
};
//success选择提供者和方法,newhost是为了如果没有对应的提供者则添加
void addprovider(const BaseConnection::ptr &newconn, const Address &newhost, const std::string &newmethod)
{
Provider::ptr newprovider;
{
std::unique_lock<std::mutex> lock(_mutex);
if (_conns.find(newconn) == _conns.end())
{
newprovider = std::make_shared<Provider>(newconn, newhost);
_conns[newconn] = newprovider;
}
else
{
newprovider = _conns[newconn];
}
std::set<Provider::ptr> &s1 = _providers[newmethod];
s1.insert(newprovider);
}
newprovider->AppendMethod(newmethod);
}
//success根据connection获取对应的提供者
Provider::ptr GetProvider(const BaseConnection::ptr &conn)
{
{
std::unique_lock<std::mutex> lock(_mutex);
auto it = _conns.find(conn);
if (it != _conns.end())
{
return it->second;
}
return nullptr;
}
}
//success删除对应的提供者
void DelProvider(const BaseConnection::ptr &conn)
{
std::unique_lock<std::mutex> lock(_mutex);
auto it = _conns.find(conn);
if (it == _conns.end())
{
return;
}
for (auto &item : it->second->methods)
{
// _providers[item].erase(it->second);
auto it1=_providers.find(item);
if(it1!=_providers.end())
{
it1->second.erase(it->second);
}
}
_conns.erase(conn);
return;
}
//success能提供方法的提供者的所有IP
std::vector<Address> HostMethod(const std::string &method)
{
std::unique_lock<std::mutex> lock(_mutex);
auto it = _providers.find(method);
if (it == _providers.end())
{
return std::vector<Address>();
}
std::vector<Address> ret;
for (auto &item : it->second)
{
ret.push_back(item->host);
}
return ret;
}
private:
std::mutex _mutex;
std::unordered_map<std::string, std::set<Provider::ptr>> _providers;
std::unordered_map<BaseConnection::ptr, Provider::ptr> _conns;
};
_providers:这个位图表示在这个管理中,某一个方法对应哪些服务端提供者
_conns:这个位图表示一个连接对应那个提供者,因为方法是一对多联系的,而连接是一对一联系的
Provider:这里我们维护了一个结构体,这个结构体用于表示一个客户端的(连接,地址,方法集合)
addprovider():添加提供者,参数包括(连接,地址,方法)
GetProvider():根据连接获取一个提供者
DelProvider():根据连接删除一个提供者
HostMethod():根据方法返回提供者的地址集合
2-2 客户端发现管理
class DiscovererManager
{
public:
using ptr = std::shared_ptr<DiscovererManager>;
//success记录一个连接和多少个那些个方法对应
struct Discoverer
{
using ptr = std::shared_ptr<Discoverer>;
std::mutex _mutex;
std::vector<std::string> methods;
BaseConnection::ptr conn;
Discoverer(const BaseConnection::ptr newconn) : conn(newconn) {}
void AddMethod(const std::string &newmethod)
{
std::unique_lock<std::mutex> lock(_mutex);
methods.push_back(newmethod);
}
};
//success增加连接的方法
Discoverer::ptr AddDiscoverer(const BaseConnection::ptr &conn, const std::string &newmethod)
{
Discoverer::ptr newdiscoverer;
// std::unique_lock<std::mutex>lock(_mutex);
{
std::unique_lock<std::mutex> lock(_mutex);
auto it = conns.find(conn);
if (it == conns.end())
{
newdiscoverer = std::make_shared<Discoverer>(conn);
conns[conn] = newdiscoverer;
ILOG("创建Discoverer客户端");
}
else
{
newdiscoverer = it->second;
ILOG("服务发现成功");
}
std::set<Discoverer::ptr> &set1 = discoverers[newmethod];
set1.insert(newdiscoverer);
}
newdiscoverer->AddMethod(newmethod);
return newdiscoverer;
}
//success删除连接
void DelDiscoverer(const BaseConnection::ptr &conn)
{
{
std::unique_lock<std::mutex> lock(_mutex);
auto it = conns.find(conn);
if (it == conns.end())
{
ILOG("不存在对应的连接");
return;
}
else
{
Discoverer::ptr discover = it->second;
auto &vec = discover->methods;
for (auto &meg : vec)
{
// discoverers[meg].erase(discover);
auto it=discoverers.find(meg);
if(it!=discoverers.end())
{
it->second.erase(discover);
}
}
}
conns.erase(conn);
}
}
//success发送一个servicerequest给客户端,让客户端在维护的map添加一个方法对应的host
void onlinenotify(const std::string &method, const Address &host)
{
notify(method,host,ServiceOptype::SERVICE_ONLINE);
}
//success发送一个servicerequest给客户端,让客户端在维护的map删除一个方法对应的host
void offlinenotify(const std::string &method, const Address &host)
{
notify(method,host,ServiceOptype::SERVICE_OFFLINE);
}
private:
//success给客户端发送一个servicerequest请求
void notify(const std::string &method, const Address &host, const ServiceOptype &optype)
{
std::set<Discoverer::ptr> it1;
{
std::unique_lock<std::mutex> lock(_mutex);
auto it = discoverers.find(method);
if (it == discoverers.end())
{
return;
}
it1 = it->second;
}
ServiceRequest::ptr msg_svr = MessageFactory::create<ServiceRequest>();
msg_svr->setHost(host);
msg_svr->setId(UUID::uuid());
msg_svr->setMethod(method);
msg_svr->setOptype(optype);
for (auto &item : it1)
{
item->conn->send(msg_svr);
}
return;
}
std::unordered_map<std::string, std::set<Discoverer::ptr>> discoverers;
// std::unordered_map<std::string,std::set<BaseConnection::ptr>> discoverers;
// std::unordered_map<std::string,std::vector<Discoverer>> discoverers;
std::unordered_map<BaseConnection::ptr, Discoverer::ptr> conns;
std::mutex _mutex;
};
discoverers:这个位图表示在这个管理中,某一个方法对应哪些客户端发现者
conns:这个位图表示一个连接对应那个发现者,因为方法是一对多联系的,而连接是一对一联系的
Discoverer:这里我们维护了一个结构体,这个结构体用于表示一个客户端的(连接,方法集合)
AddDiscoverer():添加发现者,参数包括(连接,方法)
DelDiscoverer():根据连接删除一个发现者
2-3 注册管理
class PDManager
{
public:
using ptr=std::shared_ptr<PDManager>;
PDManager():_providers(std::make_shared<ProviderManager>()),_discovers(std::make_shared<DiscovererManager>())
{}
//success注册的对外接口用于处理连接和连接发送的请求
void onServiceResponse(const BaseConnection::ptr& conn,const ServiceRequest::ptr& svr_msg)
{
ServiceOptype svopt=svr_msg->optype();
if(svopt==ServiceOptype::SERVICE_DISCOVERY)
{
ILOG("%s服务发现:%s",svr_msg->rid().c_str(),svr_msg->method().c_str());
_discovers->AddDiscoverer(conn,svr_msg->method());
return Discoverresponse(conn,svr_msg);
}
else if(svopt==ServiceOptype::SERVICE_REGISTRY)
{
ILOG("%s:%d,服务注册:%s",svr_msg->host().first.c_str(),svr_msg->host().second,svr_msg->method().c_str());
_providers->addprovider(conn,svr_msg->host(),svr_msg->method());
_discovers->onlinenotify(svr_msg->method(),svr_msg->host());
return Registryresponse(conn,svr_msg);
}
else
{
ILOG("服务类型错误");
return Errorresponse(conn,svr_msg);
}
}
//success关闭对应的连接和连接对应的服务
void onShutdown(const BaseConnection::ptr& conn)
{
auto it=_providers->GetProvider(conn);
if(it.get()!=nullptr)
{
for(auto item:it->methods)
{
_discovers->offlinenotify(item,it->host);
}
_providers->DelProvider(conn);
}
_discovers->DelDiscoverer(conn);
}
private:
//success服务错误回复
void Errorresponse(const BaseConnection::ptr& conn,const ServiceRequest::ptr& sep)
{
ServiceResponse::ptr msg_rep=MessageFactory::create<ServiceResponse>();
msg_rep->setId(sep->rid());
msg_rep->setRCode(Rcode::RCODE_INVALID_OPTYPE);
msg_rep->setoptype(ServiceOptype::SERVICE_UNKNOW);
conn->send(msg_rep);
}
//success服务注册回复serviceresponse
void Registryresponse(const BaseConnection::ptr& conn,const ServiceRequest::ptr& sep)
{
ServiceResponse::ptr msg_rep=MessageFactory::create<ServiceResponse>();
msg_rep->setId(sep->rid());
msg_rep->setRCode(Rcode::RCODE_OK);
msg_rep->setoptype(ServiceOptype::SERVICE_REGISTRY);
conn->send(msg_rep);
}
//success服务发现回复serviceresponse
void Discoverresponse(const BaseConnection::ptr& conn,const ServiceRequest::ptr& sep)
{
ServiceResponse::ptr msg_rep=MessageFactory::create<ServiceResponse>();
msg_rep->setId(sep->rid());
msg_rep->setoptype(ServiceOptype::SERVICE_DISCOVERY);
std::vector<Address> hosts=_providers->HostMethod(sep->method());
if(hosts.empty())
{
msg_rep->setRCode(Rcode::RCODE_NOT_FOUND_SERVICE);
conn->send(msg_rep);
return;
}
msg_rep->setHost(hosts);
msg_rep->setRCode(Rcode::RCODE_OK);
msg_rep->setMethod(sep->method());
conn->send(msg_rep);
}
ProviderManager::ptr _providers;
DiscovererManager::ptr _discovers;
};
_providers:提供者管理,管理了在服务注册端中有哪些提供者
_discovers:发现者管理,管理了在服务注册端中有哪些发现者
onServiceResponse():接收服务端或客户端发送过来的服务请求,如果是注册请求则调用ProviderManager的接口添加注册,并且上线DiscovererManager对于此方法的发现
onShutdown():关闭与一个服务端的连接,并且下线与该服务端有联系的服务发现
Errorresponse():错误回复,如果服务请求的处理错误,那么返回连接一个错误的服务回复
Registryresponse():注册请求回复,回复服务端一个服务回复报文
Discoverresponse():发现请求回复,回复客户端一个服务回复报文
三、业务功能层:服务端
3-1 服务端路由
- 方法描述结构体
因为服务端需要提供大量的方法,所以我们需要一个组织描述将这些方法管理起来
class ServiceDescribe
{
public:
//指向自身的指针类型
using ptr=std::shared_ptr<ServiceDescribe>;
//服务的回调函数
using ServiceCallBack=std::function<void(const Json::Value&,Json::Value&)>;
//参数类型描述
using ParamsDescribe=std::pair<std::string,VType>;
//Success构造服务函数服务包括方法名,方法参数描述,返回值类型,回调函数
ServiceDescribe(std::string&& mname,std::vector<ParamsDescribe>&& desc,
VType vtype,ServiceCallBack&& handler):
method_name(std::move(mname)),call_back(std::move(handler)),
params_desc(std::move(desc)),return_type(vtype)
{}
//Success返回函数名
const std::string& method()
{
return method_name;
}
//success校验Service的参数字段类型是否和Value类型是否相同
bool paramCheck(const Json::Value& params)
{
for(auto& desc:params_desc)
{
if(!params.isMember(desc.first))
{
ELOG("参数成员校验失败,存在缺失的参数:%s",desc.first.c_str());
return false;
}
if(!check(desc.second,params[desc.first]))
{
ELOG("参数校验失败,存在错误的类型参数:%s",desc.first.c_str());
return false;
}
}
return true;
}
//success用Service的回调函数处理参数并返回result
bool call(const Json::Value& params,Json::Value& result)
{
call_back(params,result);
if(!rtypeCheck(result))
{
ELOG("返回参数类型校验失败");
return false;
}
return true;
}
private:
//success校验返回值类型是否相同
bool rtypeCheck(const Json::Value&val)
{
return check(return_type,val);
}
//success校验Json是否对应基准值
bool check(VType vtype,const Json::Value& val)
{
switch (vtype)
{
case VType::STRING: return val.isString();
case VType::ARRAY: return val.isArray();
case VType::BOOL: return val.isBool();
case VType::INTEGRAL: return val.isIntegral();
case VType::OBJECT: return val.isObject();
case VType::NUMERIC: return val.isNumeric();
}
return false;
}
std::string method_name; //服务函数名
ServiceCallBack call_back; //服务函数
std::vector<ParamsDescribe> params_desc; //函数的参数
VType return_type; //函数的返回类型
};
这个结构体和服务端提供的一个方法关联,后面服务端会有大量的这种描述
method_name:服务方法名,服务端提供的一个服务的方法名
call_back:方法名的执行者,回调函数
params_desc:函数的参数,用于校验客户端传过来的参数是否符合服务方法的需求
return_type:返回值类型,校验返回给客户端的返回值类型是否符合要求
method():返回方法名称
paramCheck():检验客户端传递的参数是否符合条件
call():将客户端的参数传递进去,并且返回一个Json格式的结果
rtypeCheck():校验返回值类型是否相同
check():校验Json类型是否对应基准值
- 方法描述工厂
对于给服务端添加方法,我们为了 更美观选择使用工厂来生产
class ServiceDescribeFactory
{
public:
//Success
void SetMethodName(const std::string& method_name)
{
_method_name=method_name;
}
//Success
void SetServiceDescribe(const ServiceDescribe::ServiceCallBack& callback)
{
_callback=std::move(callback);
}
//Success
void SetParamsDesc(const std::string& param,VType vtype)
{
_params_desc.push_back({param,vtype});
}
//Success
void SetReturnVtype(VType vtype)
{
_return_vtype=vtype;
}
//Success
ServiceDescribe::ptr build()
{
return std::make_shared<ServiceDescribe>
(std::move(_method_name),std::move(_params_desc)
,_return_vtype,std::move(_callback));
}
private:
std::string _method_name;
ServiceDescribe::ServiceCallBack _callback;
std::vector<ServiceDescribe::ParamsDescribe>_params_desc;
VType _return_vtype;
};
_method_name:生产的方法名
_callback:方法的回调函数
_params_desc:方法的参数类型集合
_return_vtype:方法的返回值类型
build():返回一个方法描述
- 方法管理描述
既然存在这么多方法,那么我们就需要一个描述将它们统一管理起来
class ServiceManager
{
public:
using ptr=std::shared_ptr<ServiceManager>;
//success
void insert(const ServiceDescribe::ptr& service)
{
std::unique_lock<std::mutex>lock(_mutex);
_services[service->method()]=service;
}
//success
ServiceDescribe::ptr select(const std::string& servicename)
{
std::unique_lock<std::mutex>lock(_mutex);
auto it=_services.find(servicename);
if(it==_services.end())
{
ELOG("服务未发现");
// return ServiceDescribe::ptr();
return nullptr;
}
return it->second;
}
//success
void remove(const std::string& servicename)
{
std::unique_lock<std::mutex>lock(_mutex);
_services.erase(servicename);
}
private:
std::mutex _mutex;
std::unordered_map<std::string,ServiceDescribe::ptr>_services;
};
_services:方法名对应的方法描述
insert():增加一个方法描述
select():根据方法名返回一个方法描述
remove():根据方法名,删除一个方法描述
- 路由管理
既然存在多个方法描述,那么当客户端发送一个请求时,我们需要找到那个方法描述,所以我们需要一个路由管理
class RpcRouter
{
public:
using ptr=std::shared_ptr<RpcRouter>;
//success
RpcRouter():_service_manager(std::make_shared<ServiceManager>()){}
//success服务端处理报文
void onRpcRequest(const BaseConnection::ptr& conn,RpcRequest::ptr& request)
{
auto it=_service_manager->select(request->method());
if(it==nullptr)
{
ELOG("不存在对应请求的方法:%s",request->method().c_str());
return response(conn,request,Json::Value(),Rcode::RCODE_NOT_FOUND_SERVICE);
}
bool ret=it->paramCheck(request->params());
if(ret==false)
{
ELOG("参数校验错误");
return response(conn,request,Json::Value(),Rcode::RCODE_INVALID_PARAMS);
}
Json::Value result;
bool ret1=it->call(request->params(),result);
if(ret1==false)
{
ELOG("返回值错误");
return response(conn,request,Json::Value(),Rcode::RCODE_INTERNAL_ERROR);
}
return response(conn,request,result,Rcode::RCODE_OK);
}
//success注册一个服务的方法
void registerMethod(const ServiceDescribe::ptr& service)
{
_service_manager->insert(service);
}
private:
//success发送一个回复的报文
void response(const BaseConnection::ptr& conn,const RpcRequest::ptr& rqs
,const Json::Value& body,Rcode rcode)
{
RpcResponse::ptr rep=std::dynamic_pointer_cast
<RpcResponse>(MessageFactory::create(MType::RSP_RPC));
rep->setId(rqs->rid());
rep->setMType(MType::RSP_RPC);
rep->setRCode(rcode);
rep->setResult(body);
conn->send(rep);
}
ServiceManager::ptr _service_manager;
};
_service_manager:之前我们组织的方法集合
onRpcRequest():接收客户端的方法请求,并查询路由中是否存在该方法,存在则调用该方法,并返回给客户端回调结果,不存在则返回给客户端一个错误报文
registerMethod():将方法描述注册进路由中
response():回复给客户端一个RPC回复
3-2 服务注册客户端
- 服务提供者
一个服务端中需要有一个客户端专门连接服务注册端,专门用来和注册端通信,所以我们需要将服务端的提供者组织描述一下
class Provider
{
public:
using ptr = std::shared_ptr<Provider>;
Provider(const Requestor::ptr &requestor) : _requestor(requestor) {}
// success注册方法,客户端也是可以带着地址去注册方法的
bool registrymethod(const BaseConnection::ptr &conn, const std::string &method, const Address &host)
{
ServiceRequest::ptr seq = MessageFactory::create<ServiceRequest>();
seq->setHost(host);
seq->setMethod(method);
seq->setId(UUID::uuid());
seq->setOptype(ServiceOptype::SERVICE_REGISTRY);
BaseMessage::ptr rep;
bool ret = _requestor->send(conn, seq, rep);
if (ret == false)
{
ILOG("发送失败%s:%s", seq->method().c_str(), seq->rid().c_str());
return false;
}
ServiceResponse::ptr sep = std::dynamic_pointer_cast<ServiceResponse>(rep);
if (sep.get() == nullptr)
{
ILOG("向下转换类型失败");
return false;
}
if (sep->rcode() != Rcode::RCODE_OK)
{
ILOG("请求处理失败:%s", errReason(sep->rcode()).c_str());
return false;
}
ILOG("发送请求处理成功");
return true;
}
private:
Requestor::ptr _requestor;
};
_requestor:不管什么客户端都需要一个Requestor类来发送给接收处理回复报文
registrymethod():向服务注册端发送服务注册请求,通过Requestor
- 服务注册客户端
class RegistryClient
{
public:
using ptr=std::shared_ptr<RegistryClient>;
RegistryClient(const std::string& ip,const int& port):
_requestor(std::make_shared<Requestor>()),
_dispatcher(std::make_shared<Dispatcher>()),
_client(Clientfactory::create(ip,port)),
_provider(std::make_shared<Provider>(_requestor))
{
auto req=std::bind(&Requestor::onResponse,_requestor.get(),std::placeholders::_1,std::placeholders::_2);
_dispatcher->registerHandler<BaseMessage>(MType::RSP_SERVICE,req);
auto dis=std::bind(&Dispatcher::OnMessage,_dispatcher.get(),std::placeholders::_1,std::placeholders::_2);
_client->setMessageCallback(dis);
_client->connect();
}
bool RegistryProvider(const std::string &method, const Address &host)
{
return _provider->registrymethod(_client->connection(),method,host);
}
private:
Requestor::ptr _requestor;
Dispatcher::ptr _dispatcher;
BaseClient::ptr _client;
Provider::ptr _provider;
};
_dispatcher:这里的Dispatcher主要是起到一层保险作用,防止将不是报文回复的服务也传进Requestor中
_requestor:报文转接作用和处理
_client:用于和服务注册端进行连接
_provider:服务提供描述,向服务注册端发送注册请求
四、业务功能层:客户端
3-1 客户端发现
既然服务端有存储服务描述的组织,那么客户端也要存储服务发现的组织,我们需要有一个组织记录客户端发现的服务端地址有哪些
- 服务名地址管理
class MethodHost
{
public:
using ptr = std::shared_ptr<MethodHost>;
MethodHost() : _idx(0)
{
}
MethodHost(const std::vector<Address> &hosts) : _idx(0), _hosts(hosts.begin(), hosts.end())
{
}
void AddMethodHost(const Address &host)
{
std::unique_lock<std::mutex> lock(_mutex);
_hosts.push_back(host);
}
void RemoveHost(const Address &host)
{
std::unique_lock<std::mutex> lock(_mutex);
for (auto it = _hosts.begin(); it != _hosts.end(); it++)
{
if (it->second == host.second && it->first == host.first)
{
_hosts.erase(it);
break;
}
}
}
Address GetHost()
{
std::unique_lock<std::mutex> lock(_mutex);
if (!_hosts.empty())
{
size_t index = (_idx++) % _hosts.size();
return _hosts[index];
}
// return _hosts[index];
return Address();
}
bool empty()
{
std::unique_lock<std::mutex> lock(_mutex);
return _hosts.empty();
}
private:
std::mutex _mutex;
size_t _idx;
std::vector<Address> _hosts;
};
_idx:用作轮询算法的参数
_hosts:用于记录服务端的地址端口数组
AddMethodHost():用于添加服务端的地址和端口
RemoveHost() :删除一个服务端的地址和端口
GetHost():在这个类当中,它所有的地址和端口只对应一个服务名,所以这里的获取涉及到轮询访问
empty():判断这个方法对应的服务端的地址和端口是否为空
- 服务发现管理
既然客户端可以发现多个服务,那么就需要让这些服务和地址都对应起来
class Discoverer
{
public:
using ptr = std::shared_ptr<Discoverer>;
using offlinefunction = std::function<void(const Address &)>;
Discoverer(const offlinefunction &offfunction, const Requestor::ptr &requestor) : _off_function(offfunction), _requestor(requestor)
{}
// success查找对应的method服务,如果没有该服务则发送一个服务请求,收到服务回复则构建一个服务
bool ServiceDiscover(const BaseConnection::ptr &conn, const std::string &method, Address &host)
{
{
std::unique_lock<std::mutex> lock(_mutex);
auto it = MethodHosts.find(method);
if (it!= MethodHosts.end())
{
// auto it = MethodHosts.find(method);
if (it->second && !it->second->empty())
{
host = it->second->GetHost();
return true;
}
}
}
ServiceRequest::ptr req = MessageFactory::create<ServiceRequest>();
req->setId(UUID::uuid());
req->setMethod(method);
req->setOptype(ServiceOptype::SERVICE_DISCOVERY);
BaseMessage::ptr rep;
bool ret = _requestor->send(conn, req, rep);
if (ret == false)
{
ELOG("服务发现失败");
return false;
}
ServiceResponse::ptr msg = std::dynamic_pointer_cast<ServiceResponse>(rep);
if (msg == nullptr)
{
ILOG("向下类型转化失败");
return false;
}
if (msg->rcode() != Rcode::RCODE_OK)
{
ELOG("消息返回码错误:%s", errReason(msg->rcode()).c_str());
return false;
}
// auto it=MethodHosts.find(method);
std::vector<Address> hosts = msg->hosts();
MethodHost::ptr newhosts = std::make_shared<MethodHost>(hosts);
if (newhosts->empty())
{
ELOG("无该服务的提供");
return false;
}
{
std::unique_lock<std::mutex> lock(_mutex);
host = newhosts->GetHost();
MethodHosts[method] = newhosts;
return true;
}
}
void onServiceRequest(const BaseConnection::ptr &conn, const ServiceRequest::ptr &msg)
{
{
std::unique_lock<std::mutex>lock(_mutex);
if(msg->optype()==ServiceOptype::SERVICE_ONLINE)
{
auto it=MethodHosts.find(msg->method());
if(it!=MethodHosts.end())
{
it->second->AddMethodHost(msg->host());
}
else
{
MethodHost::ptr newMethodHost=std::make_shared<MethodHost>();
newMethodHost->AddMethodHost(msg->host());
MethodHosts[msg->method()]=newMethodHost;
}
return;
}
else if(msg->optype()==ServiceOptype::SERVICE_OFFLINE)
{
auto it=MethodHosts.find(msg->method());
if(it!=MethodHosts.end())
{
it->second->RemoveHost(msg->host());
}
else
{
ELOG("不存在该服务");
return;
}
}
else
{
ELOG("服务操作类型错误");
return;
}
}
_off_function(msg->host());
}
private:
std::mutex _mutex;
// success消息转接区
Requestor::ptr _requestor;
offlinefunction _off_function;
// success一个服务对应的几个服务器地址
std::unordered_map<std::string, MethodHost::ptr> MethodHosts;
};
_off_function:当一个连接断开后,它的地址和端口会传给RpcClient,然后回调函数再执行删除这个客户端微服务
ServiceDiscover() :没有发现该服务则向服务注册端发送一个服务发现请求,发现了该服务则直接返回服务器的地址
onServiceRequest():接收服务注册端发送到客户端的服务请求,如果是服务下线,则调用客户端的回调函数
3-2 客户端发现服务
将服务发现功能集合到一个客户端中
class DiscoveryClient
{
public:
using ptr=std::shared_ptr<DiscoveryClient>;
DiscoveryClient(const std::string& ip,const int& port,const Discoverer::offlinefunction& offFunction)
:_requestor(std::make_shared<Requestor>()),
_discover(std::make_shared<Discoverer>(offFunction,_requestor)),
_client(Clientfactory::create(ip,port)),
_dispatcher(std::make_shared<Dispatcher>())
{
//success这个MType::REQ_SERVICE一般用于注册服务端对客户端进行上线或下线的通知
auto req=bind(&Discoverer::onServiceRequest,_discover.get(),std::placeholders::_1,std::placeholders::_2);
_dispatcher->registerHandler<ServiceRequest>(MType::REQ_SERVICE,req);
//success当服务端发送一个服务发现请求后,这里的Requestor将会接收到注册中心返回的请求,并将服务的地址保存起来
auto rep=bind(&Requestor::onResponse,_requestor.get(),std::placeholders::_1,std::placeholders::_2);
_dispatcher->registerHandler<BaseMessage>(MType::RSP_SERVICE,rep);
auto dis=bind(&Dispatcher::OnMessage,_dispatcher.get(),std::placeholders::_1,std::placeholders::_2);
_client->setMessageCallback(dis);
_client->connect();
}
bool ServiceDiscover(const std::string& method,Address& host)
{
//success讲host设置为method对应的服务,如果没有发现method,则向服务注册中心发送一个注册请求
return _discover->ServiceDiscover(_client->connection(),method,host);
}
private:
Requestor::ptr _requestor;
Discoverer::ptr _discover; //success存储了客户端已经发现的服务
// Requestor::ptr _requestor;
BaseClient::ptr _client;
Dispatcher::ptr _dispatcher;
};
这里将Discoverer封装进一个客户端中进行管理
_requestor:消息转发管理,每个客户端都要有
_dispatcher:消息类型转发管理
_discover:存储了客户端连接的方法和对应的地址,并且接收
这里涉及到客户端接收服务请求关于服务的上线和下线和服务的的回复对应Requestor
3-3 客户端服务响应
我们需要设置一个客户端专门发送客户端的请求的封装类
class RpcCaller
{
public:
using ptr=std::shared_ptr<RpcCaller>;
using JsonAsyncResponse=std::future<Json::Value>;
using JsonResponseCallBack=std::function<void(const Json::Value&)>;
RpcCaller(const Requestor::ptr& requestor):_requestor(requestor){}
//success同步调用,这里面有个有意思的设置,先设置了一个异步的send,然后在获取异步的send返回值的future就成了同步的send
bool call(const BaseConnection::ptr& conn,const std::string& method,
const Json::Value& params,Json::Value& result)
{
auto req=MessageFactory::create<RpcRequest>();
req->setParams(params);
req->setId(UUID::uuid());
req->setMethod(method);
req->setMType(MType::REQ_RPC);
BaseMessage::ptr rep;
bool ret=_requestor->send(conn,req,rep);
if(!ret)
{
ELOG("同步请求成功但未获取到响应对象(rep is null)");
return false;
}
RpcResponse::ptr result_rep=std::dynamic_pointer_cast<RpcResponse>(rep);
if(!result_rep)
{
ELOG("响应类型错误,期望RpcResponse,实际类型不匹配");
return false;
}
if(result_rep->rcode()!=Rcode::RCODE_OK)
{
ELOG("返回结果表示不正确,%s",errReason(result_rep->rcode()).c_str());
return false;
}
ELOG("返回完成");
result=result_rep->result();
return true;
}
//success发送request请求,给予一个future,返回一个异步的future
bool call(const BaseConnection::ptr& conn,const std::string& method,
const Json::Value& params,JsonAsyncResponse& result)
{
RpcRequest::ptr rp=MessageFactory::create<RpcRequest>();
rp->setId(UUID::uuid());
rp->setMethod(method);
rp->setMType(MType::REQ_RPC);
rp->setParams(params);
auto it=std::make_shared<std::promise<Json::Value>>();
result=it->get_future();
auto cb=std::bind(&RpcCaller::callback,this,it,std::placeholders::_1);
bool ret=_requestor->send(conn,rp,cb);
if(ret==false)
{
ELOG("消息发送失败");
return false;
}
return true;
}
//success发送request请求,给予一个回调函数,不返回
bool call(const BaseConnection::ptr& conn,const std::string& method,
const Json::Value& params,const JsonResponseCallBack& callback)
{
RpcRequest::ptr rp=MessageFactory::create<RpcRequest>();
rp->setMethod(method);
rp->setId(UUID::uuid());
rp->setMType(MType::REQ_RPC);
rp->setParams(params);
auto it=std::bind(&RpcCaller::callbackfunc,this,callback,std::placeholders::_1);
bool ret=_requestor->send(conn,rp,it);
if(ret==false)
{
ELOG("发送消息失败");
return false;
}
return true;
}
private:
//success不获取Json::Value的结果,直接调用设置的回调函数
void callbackfunc(const JsonResponseCallBack& cb,const BaseMessage::ptr& msg)
{
auto item=std::dynamic_pointer_cast<RpcResponse>(msg);
if(!item)
{
ELOG("消息类型向下转换失败");
return;
}
if(item->rcode()!=Rcode::RCODE_OK)
{
ELOG("请求出错,错误信息为:%s",errReason(item->rcode()).c_str());
return;
}
cb(item->result());
}
//success异步获取服务端返回的msg中的Json::Value
void callback(std::shared_ptr<std::promise<Json::Value>> result,const BaseMessage::ptr& msg)
{
auto item=std::dynamic_pointer_cast<RpcResponse>(msg);
if(!item)
{
ELOG("消息类型向下转换失败");
return;
}
if(item->rcode()!=Rcode::RCODE_OK)
{
ELOG("请求出错,错误信息为:%s",errReason(item->rcode()).c_str());
return;
}
result->set_value(item->result());
}
Requestor::ptr _requestor;
};
-
同步调用call:用于将参数打包发送同步请求,如果结果result未到达则阻塞 -
异步调用call:用于将参数打包发送异步请求,返回一个future -
回调函数call:返回的结果使用设置好的回调函数处理
五、应用接口层:服务注册端
class RegistryServer
{
public:
using ptr=std::shared_ptr<RegistryServer>;
RegistryServer(const int& port):_dispatcher(std::make_shared<Dispatcher>()),
_pdmanager(std::make_shared<PDManager>())
{
_server=Serverfactory::create(port);
auto it1=std::bind(&PDManager::onServiceResponse,_pdmanager.get(),std::placeholders::_1,std::placeholders::_2);
_dispatcher->registerHandler<ServiceRequest>(MType::REQ_SERVICE,it1);
auto it2=std::bind(&Dispatcher::OnMessage,_dispatcher.get(),std::placeholders::_1,std::placeholders::_2);
_server->setMessageCallback(it2);
auto it3=std::bind(&RegistryServer::ShutDown,this,std::placeholders::_1);
_server->setCloseCallback(it3);
}
void Start()
{
_server->start();
}
void ShutDown(const BaseConnection::ptr conn)
{
_pdmanager->onShutdown(conn);
}
private:
BaseServer::ptr _server;
Dispatcher::ptr _dispatcher;
PDManager::ptr _pdmanager;
};
让PDManager接收所有发Rpc请求,并且服务注册端只接受服务请求报文
Start():开始运行服务
ShutDown():关闭连接,服务端和客户端的连接都关闭
六、应用接口层:服务端
class RpcServer
{
public:
using ptr=std::shared_ptr<RpcServer>;
RpcServer(const Address& access_addr,bool enableRegistry=false,const Address& registry_server_addr=Address())
:_enableRegistry(enableRegistry),
_access_addr(access_addr),
_router(std::make_shared<RpcRouter>()),
_dispatcher(std::make_shared<Dispatcher>())
{
if(_enableRegistry)
{
_reg_client=std::make_shared<client::RegistryClient>
(registry_server_addr.first,registry_server_addr.second);
}
// _router=std::make_shared<RpcRouter>();
auto it1=std::bind(&RpcRouter::onRpcRequest,_router.get()
,std::placeholders::_1,std::placeholders::_2);
_dispatcher->registerHandler<RpcRequest>(MType::REQ_RPC,it1);
auto it2=std::bind(&Dispatcher::OnMessage,_dispatcher.get()
,std::placeholders::_1,std::placeholders::_2);
_server=Serverfactory::create(access_addr.second);
_server->setMessageCallback(it2);
}
void RegistryMethod(const ServiceDescribe::ptr& service )
{
if(_enableRegistry)
{
_reg_client->RegistryProvider(service->method(),_access_addr);
}
_router->registerMethod(service);
}
void Start()
{
_server->start();
}
private:
bool _enableRegistry;
Address _access_addr;
client::RegistryClient::ptr _reg_client;
RpcRouter::ptr _router;
Dispatcher::ptr _dispatcher;
BaseServer::ptr _server;
};
这里的服务端只接收Rpc请求,并且接收到后全部交给路由处理
RegistryMethod():添加一个服务描述,并发送给服务注册端
七、应用接口层:客户端
class RpcClient
{
public:
using ptr=std::shared_ptr<RpcClient>;
RpcClient(bool enableDiscovery,const std::string& ip,const int& port):
_enableDiscovery(enableDiscovery),
_requestor(std::make_shared<Requestor>()),
_dispatcher(std::make_shared<Dispatcher>()),
_caller(std::make_shared<RpcCaller>(_requestor))
{
//success这里是等_caller调用完成之后,清空发送的描述信息
auto rsp_cb=std::bind(&Requestor::onResponse,_requestor.get(),std::placeholders::_1,std::placeholders::_2);
_dispatcher->registerHandler<BaseMessage>(MType::RSP_RPC,rsp_cb);
if(enableDiscovery)
{
auto offline=std::bind(&RpcClient::DelClient,this,std::placeholders::_1);
_discovery_client=std::make_shared<DiscoveryClient>(ip,port,offline);
}
else
{
auto message_dis=std::bind(&Dispatcher::OnMessage,_dispatcher.get()
,std::placeholders::_1,std::placeholders::_2);
_rpc_client=Clientfactory::create(ip,port);
_rpc_client->setMessageCallback(message_dis);
_rpc_client->connect();
}
}
//success这里的_caller会根据服务对应的客户端的connection将消息发送出去,并且同一由同一个Requestor来处理回复
bool call(const std::string& method,const Json::Value& params,Json::Value& result)
{
auto it=GetClient(method);
if(it==nullptr)
{
ELOG("获取客户端失败");
return false;
}
return _caller->call(it->connection(),method,params,result);
}
bool call(const std::string& method,const Json::Value& params,RpcCaller::JsonAsyncResponse& result)
{
auto it=GetClient(method);
if(it==nullptr)
{
ELOG("获取客户端失败");
return false;
}
return _caller->call(it->connection(),method,params,result);
}
bool call(const std::string& method,const Json::Value& params,RpcCaller::JsonResponseCallBack& result)
{
auto it=GetClient(method);
if(it==nullptr)
{
ELOG("获取客户端失败");
return false;
}
return _caller->call(it->connection(),method,params,result);
}
private:
BaseClient::ptr NewClient(const Address& host)
{
//success这里增加的所有客户端的Rep都将在同一个_requestor中处理
auto dis=std::bind(&Dispatcher::OnMessage,_dispatcher.get(),std::placeholders::_1,std::placeholders::_2);
BaseClient::ptr newclient=Clientfactory::create(host.first,host.second);
// PutClient(host,newclient);
newclient->setMessageCallback(dis);
newclient->connect();
PutClient(host,newclient);
return newclient;
}
BaseClient::ptr GetClient(const Address& host)
{
std::unique_lock<std::mutex>lock(_mutex);
auto it=_rpc_clients.find(host);
if(it!=_rpc_clients.end())
{
return it->second;
}
return nullptr;
}
BaseClient::ptr GetClient(const std::string& method)
{
Address host;
BaseClient::ptr retclient;
if(_enableDiscovery)
{
bool ret=_discovery_client->ServiceDiscover(method,host);
//success这里如果没有发现服务,则返回nullptr
if(ret==false)
{
ELOG("无该方法的服务");
return nullptr;
}
//success根据返回来的地址,获取客户端,如果没有则创建
retclient=GetClient(host);
if(retclient==nullptr)
{
ILOG("开始创建client");
retclient=NewClient(host);
}
}
else
{
retclient=_rpc_client;
}
return retclient;
}
void PutClient(const Address& host,const BaseClient::ptr& client)
{
std::unique_lock<std::mutex>lock(_mutex);
_rpc_clients.insert(std::make_pair(host,client));
}
void DelClient(const Address& host)
{
std::unique_lock<std::mutex>lock(_mutex);
_rpc_clients.erase(host);
}
private:
struct AddHash
{
size_t operator()(const Address& addr) const
{
std::string AddString=addr.first+std::to_string(addr.second);
return std::hash<std::string>{}(AddString);
}
};
bool _enableDiscovery;
DiscoveryClient::ptr _discovery_client;
Requestor::ptr _requestor;
RpcCaller::ptr _caller;
Dispatcher::ptr _dispatcher;
BaseClient::ptr _rpc_client;
std::mutex _mutex;
std::unordered_map<Address,BaseClient::ptr,AddHash> _rpc_clients; //success服务端的地址对应客户端的指针
};
_discovery_client:服务发现客户端,是一个子客户端
_caller:调用,和父客户端共用一个Requestor
_rpc_clients:一个小型的微服务,因为客户端需要多个服务端的方法,所以建立了多个BaseClient来连接客户端
AddHash():用于哈希表排列的仿函数
PutClient():将一个服务端地址和客户端添加到哈希表中
DelClient():删除一个服务端地址对应的连接
GetClient():通过方法名来获取对应微服务客户端,没有该方法者服务发现管理去发现,如果已经发现过了则返回地址,如果未发现过则发送一个服务请求给服务注册端,返回服务端的地址
NewClient():通过服务端的地址,来创建一个客户端和它进行连接
call():异步,同步,函数回调,用的是caller的接口,caller用的是父客户端的Requestor收发处理报文
134

被折叠的 条评论
为什么被折叠?



