文章目录
- 一、业务层的实现
-
- [1. Dispatcher模块](#1. Dispatcher模块)
- [2. Requestor模块](#2. Requestor模块)
- [3. RpcCaller模块](#3. RpcCaller模块)
- [4. RpcRouter模块](#4. RpcRouter模块)
- [5. Registry-Discovery模块](#5. Registry-Discovery模块)
- [6. Publish-Subscribe模块](#6. Publish-Subscribe模块)
- [7. server模块](#7. server模块)
- [8. client模块](#8. client模块)
项目代码:https://github.com/luoyu524/Json_Rpc
项目文档:https://blog.csdn.net/2402_86681376/category_13166697.html
一、业务层的实现
1. Dispatcher模块
这个模块中,作为一个分发模块,会保存一个hash_map<消息类型, 回调函数>,以此由使用者来决定哪条消息用哪个业务函数进行处理。
但是,一个消息类型对应的回调函数中一定会有一个参数,是消息本身。这个参数类型不同,导致回调函数的类型不同,不同的类型无法记录到一张哈希表中。
所以,我们设计成hash_map的value类型为一个基类指针类型,而每一种具体回调函数继承该基类。hash_map的value对象就都能指向每一个回调函数类型指针了。
cpp
// dispatcher.hpp
#pragma once
#include "Base.hpp"
#include "Logger.hpp"
#include "net.hpp"
#include "message.hpp"
#include "fields.hpp"
#include <memory>
namespace RPC
{
class CallBack
{
public:
using ptr = std::shared_ptr<CallBack>;
virtual void onMessage(const BaseConnection::ptr& conn, BaseMessage::ptr& msg) = 0;
};
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)>;
CallBackT(const MessageCallback& handler)
:_handler(handler)
{}
void onMessage(const BaseConnection::ptr &conn, BaseMessage::ptr &msg) override
{
auto type_msg = std::dynamic_pointer_cast<T>(msg);
_handler(conn, type_msg);
}
private:
MessageCallback _handler;
};
class Dispatcher
{
public:
using ptr = std::shared_ptr<Dispatcher>;
// 这个函数对外提供,注册 消息类型------回调函数 映射的接口
template<typename T>
void registerHandler(MsgType mtype, const typename CallBackT<T>::MessageCallBack& handler)
{
std::unique_lock<std::mutex> lock(_mutex);
auto cb = std::make_shared<CallBackT<T>>(handler);
_handlers.insert(std::make_pair(mtype, cb));
}
// 这个函数对外提供,消息处理接口
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);
}
LOG(LogLevel::ERROR) << "收到未知类型的消息: " << (int)msg->mtype();
conn->shutdown();
}
private:
std::mutex _mutex;
std::unordered_map<MsgType, CallBack::ptr> _handlers;
};
}
2. Requestor模块
Requestor模块存在的意义:管理起每一条请求,以便于对请求对应的响应做出合适的操作。
我们给每一个请求都设定一个请求ID,服务端进行响应的时候标识响应针对的是哪个请求(也就是响应信息中会包含请求ID)。因此客户端这边我们不管收到哪条请求的响应,将数据存储入一个hash_map中,以请求ID作为映射,并向外提供获取指定请求ID响应的阻塞接口,这样只要在发送请求的时候知道自己的请求ID,那么就能获取到自己想要的响应。
再进一步,可以将每个请求进一步封装描述,添加入异步future控制、或者设置回调函数的方式。不仅可以阻塞获取响应,也可以实现异步获取响应以及回调处理响应。
cpp
// Requestor.hpp
#pragma once
#include "../common/net.hpp"
#include "../common/message.hpp"
#include <future>
#include <functional>
namespace RPC
{
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;
ReqType rtype;
std::promise<BaseMessage::ptr> response;
RequestCallback callback;
};
// 这个函数会注册到Dispatcher模块,是客户端针对收到一条Rpc响应进行回调处理的业务函数
void onResponse(const BaseConnection::ptr& conn, BaseMessage::ptr& msg)
{
// 根据rid,找到这条响应对应的请求,根据请求中的ReqType判断怎么处理响应
std::string rid = msg->rid();
RequestDescribe::ptr rdp = getDescribe(rid);
if(rdp.get() == nullptr)
{
LOG(LogLevel::ERROR) << "收到响应" << rid << "但是未找到对应的请求描述!";
return;
}
if(rdp->rtype == ReqType::REQ_ASYNC)
{
rdp->response.set_value(msg);
}
else if(rdp->rtype == ReqType::REQ_CALLBACK)
{
if(rdp->callback)
rdp->callback(msg);
}
else
{
LOG(LogLevel::ERROR) << "未知的请求类型!";
}
delDescribe(rid);
}
// 同步方式请求
bool send(const BaseConnection::ptr& conn, const BaseMessage::ptr& req, BaseMessage::ptr& rsp)
{
AsyncResponse rsp_future;
bool ret = send(conn, req, rsp_future);
if (ret == false)
{
return false;
}
// 其实还是异步的send,只是这里同步获取结果,外界感知还是同步的
rsp = rsp_future.get();
return true;
}
// 异步方式请求
bool send(const BaseConnection::ptr& conn, const BaseMessage::ptr& req, AsyncResponse& async_rsp)
{
RequestDescribe::ptr rdp = newDescribe(req, ReqType::REQ_ASYNC);
if (rdp.get() == nullptr)
{
LOG(LogLevel::ERROR) << "构造请求描述对象失败!";
return false;
}
conn->send(req);
async_rsp = rdp->response.get_future();
return true;
}
// 回调方式请求
bool send(const BaseConnection::ptr& conn, const BaseMessage::ptr& req, const RequestCallback& cb)
{
RequestDescribe::ptr rdp = newDescribe(req, ReqType::REQ_CALLBACK, cb);
if (rdp.get() == nullptr)
{
LOG(LogLevel::ERROR) << "构造请求描述对象失败!";
return false;
}
conn->send(req);
return true;
}
private:
RequestDescribe::ptr newDescribe(const BaseMessage::ptr& req, ReqType rtype, const RequestCallback& cb = RequestCallback())
{
std::unique_lock<std::mutex> lock(_mutex);
RequestDescribe::ptr rd = std::make_shared<RequestDescribe>();
rd->request = req;
rd->rtype = rtype;
if (rtype == ReqType::REQ_CALLBACK && cb)
{
rd->callback = cb;
}
_request_desc.insert(std::make_pair(req->rid(), rd));
return rd;
}
RequestDescribe::ptr getDescribe(const std::string &rid)
{
std::unique_lock<std::mutex> lock(_mutex);
auto it = _request_desc.find(rid);
if(it == _request_desc.end())
{
return RequestDescribe::ptr();
}
return it->second;
}
void delDescribe(const std::string &rid)
{
std::unique_lock<std::mutex> lock(_mutex);
_request_desc.erase(rid);
}
private:
std::mutex _mutex;
std::unordered_map<std::string, RequestDescribe::ptr> _request_desc; // <rid---一条请求>的映射
};
}
}
3. RpcCaller模块
这个模块向我们提供实际发起Rpc请求的接口,内部使用Resquestor管理请求与发送。
Rpc调用我们需要提供多种不同方式的调用:
- 同步调用:发起调用后,等收到响应结果后返回
- 异步调用:发起调用后立即返回,在想获取结果的时候进行获取
- 回调调用:发起调用的同时设置结果的处理回调,收到响应后自动对结果进行回调处理
cpp
// RpcCaller.hpp
#pragma once
#include "Requestor.hpp"
#include <jsoncpp/json/value.h>
#include <memory>
namespace RPC
{
namespace client
{
// 用户通过RpcCaller的接口发送Rpc请求,RpcCaller内部组织好一条请求,再通过Requestor发送
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)
{}
// 同步调用
bool call(const BaseConnection::ptr& conn, const std::string& method, const Json::Value& params, Json::Value& result)
{
// 1.组织请求
auto req_msg = MsgFactory::create<RpcRequest>();
req_msg->setId(UUID::uuid());
req_msg->setMsgtype(MsgType::REQ_RPC);
req_msg->setMethod(method);
req_msg->setParams(params);
// 2.发送请求
BaseMessage::ptr rsp_msg;
// 调用重载函数必须参数类型一致
bool ret = _requestor->send(conn, std::dynamic_pointer_cast<BaseMessage>(req_msg), rsp_msg);
if (ret == false)
{
LOG(LogLevel::ERROR) << "同步Rpc请求失败!";
return false;
}
// 3.等待响应
auto rpc_rsp_msg = std::dynamic_pointer_cast<RpcResponse>(rsp_msg);
if(!rpc_rsp_msg)
{
LOG(LogLevel::ERROR) << "rpc响应向下类型转换失败!";
return false;
}
if(rpc_rsp_msg->rcode() != RCode::RCODE_OK)
{
LOG(LogLevel::ERROR) << "rpc请求出错: " << errReason(rpc_rsp_msg->rcode());
return false;
}
// 4.设置结果
result = rpc_rsp_msg->result();
return true;
}
// 异步调用
bool call(const BaseConnection::ptr& conn, const std::string& method, const Json::Value& params, JsonAsyncResponse& result)
{
auto req_msg = MsgFactory::create<RpcRequest>();
req_msg->setId(UUID::uuid());
req_msg->setMsgtype(MsgType::REQ_RPC);
req_msg->setMethod(method);
req_msg->setParams(params);
auto json_promise = std::make_shared<std::promise<Json::Value>>();
result = json_promise->get_future();
Requestor::RequestCallback cb = std::bind(&RpcCaller::AsyncCallback, this, json_promise, std::placeholders::_1);
bool ret = _requestor->send(conn, std::dynamic_pointer_cast<BaseMessage>(req_msg), cb);
if(ret == false)
{
LOG(LogLevel::ERROR) << "异步rpc请求失败!";
return false;
}
return true;
}
// 回调函数调用
bool call(const BaseConnection::ptr& conn, const std::string& method, const Json::Value& params, const JsonResponseCallback& cb)
{
auto req_msg = MsgFactory::create<RpcRequest>();
req_msg->setId(UUID::uuid());
req_msg->setMsgtype(MsgType::REQ_RPC);
req_msg->setMethod(method);
req_msg->setParams(params);
Requestor::RequestCallback req_cb = std::bind(&RpcCaller::CbCallback, this, cb, std::placeholders::_1);
bool ret = _requestor->send(conn, std::dynamic_pointer_cast<BaseMessage>(req_msg), req_cb);
if(ret == false)
{
LOG(LogLevel::ERROR) << "回调rpc请求失败!";
return false;
}
return true;
}
private:
void AsyncCallback(std::shared_ptr<std::promise<Json::Value>> result, const BaseMessage::ptr& msg)
{
auto rpc_rsp_msg = std::dynamic_pointer_cast<RpcResponse>(msg);
if (!rpc_rsp_msg)
{
LOG(LogLevel::ERROR) << "rpc响应向下类型转换失败!";
return;
}
if (rpc_rsp_msg->rcode() != RCode::RCODE_OK)
{
LOG(LogLevel::ERROR) << "rpc异步请求出错: " << errReason(rpc_rsp_msg->rcode());
return;
}
result->set_value(rpc_rsp_msg->result());
}
void CbCallback(const JsonResponseCallback& cb, const BaseMessage::ptr& msg)
{
auto rpc_rsp_msg = std::dynamic_pointer_cast<RpcResponse>(msg);
if (!rpc_rsp_msg)
{
LOG(LogLevel::ERROR) << "rpc响应向下类型转换失败!";
return;
}
if (rpc_rsp_msg->rcode() != RCode::RCODE_OK)
{
LOG(LogLevel::ERROR) << "rpc回调请求出错: " << errReason(rpc_rsp_msg->rcode());
return;
}
cb(rpc_rsp_msg->result());
}
private:
Requestor::ptr _requestor;
};
}
}
4. RpcRouter模块
这个模块是服务端真正管理起来所有的服务信息的模块。
调用一个服务时,我们必须检测传入的参数和返回值是否符合这个服务的要求。
cpp
// RpcRouter.hpp
#pragma once
#include "../common/message.hpp"
#include <jsoncpp/json/value.h>
#include <memory>
#include <mutex>
#include <vector>
namespace RPC
{
namespace server
{
// 枚举每一种Json::Value成员类型
enum class ValType
{
BOOL,
INTEGRAL,
NUMERIC,
STRING,
ARRAY,
OBJECT,
};
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, ValType>; //参数名字--参数类型
ServiceDescribe(std::string&& mname, std::vector<ParamsDescribe>&& desc, ValType vtype, ServiceCallBack &&handler)
: _method_name(std::move(mname))
, _callback(std::move(handler))
, _params_desc(std::move(desc))
, _return_type(vtype)
{}
const std::string& method()
{
return _method_name;
}
// 检查提供的参数字段/类型,是否满足这个服务要求
bool paramCheck(const Json::Value& params)
{
for(auto& desc : _params_desc)
{
if(params.isMember(desc.first) == false)
{
LOG(LogLevel::ERROR) << "参数字段完整性校验失败!" << desc.first << "字段缺失!";
return false;
}
if(checkType(desc.second, params[desc.first]) == false)
{
LOG(LogLevel::ERROR) << "参数类型校验失败!" << desc.first << "类型错误!";
return false;
}
}
return true;
}
// 真正调用服务的方法功能
bool call(const Json::Value& params, Json::Value& result)
{
_callback(params, result);
if(checkType(_return_type, result) == false)
{
LOG(LogLevel::ERROR) << "回调处理函数中的响应信息类型错误";
return false;
}
return true;
}
private:
bool checkType(ValType vtype, const Json::Value& val)
{
switch(vtype)
{
case ValType::BOOL : return val.isBool();
case ValType::INTEGRAL : return val.isIntegral();
case ValType::NUMERIC : return val.isNumeric();
case ValType::STRING : return val.isString();
case ValType::ARRAY : return val.isArray();
case ValType::OBJECT : return val.isObject();
}
return false;
}
private:
std::string _method_name; // 方法名称
ServiceCallBack _callback; // 一个服务的真正方法功能函数
std::vector<ParamsDescribe> _params_desc; // 参数字段描述
ValType _return_type; // 方法函数返回值类型
};
// 建造者模式
class ServiceDescFactory
{
public:
void setMethodName(const std::string& name)
{
_method_name = name;
}
void setReturnType(ValType vtype)
{
_return_type = vtype;
}
void setParamsDesc(const std::string& pname, ValType vtype)
{
_params_desc.push_back(ServiceDescribe::ParamsDescribe(pname, vtype));
}
void setCallback(const ServiceDescribe::ServiceCallBack& cb)
{
_callback = cb;
}
ServiceDescribe::ptr build()
{
return std::make_shared<ServiceDescribe>(std::move(_method_name), std::move(_params_desc), _return_type, std::move(_callback));
}
private:
std::string _method_name;
ServiceDescribe::ServiceCallBack _callback;
std::vector<ServiceDescribe::ParamsDescribe> _params_desc;
ValType _return_type;
};
// 所有服务的管理类
class ServiceManager
{
public:
using ptr = std::shared_ptr<ServiceManager>;
// 新增一个服务
void insert(const ServiceDescribe::ptr& desc)
{
std::unique_lock<std::mutex> lock(_mutex);
_services.insert(std::make_pair(desc->method(), desc));
}
// 查找一个服务
ServiceDescribe::ptr select(const std::string& method_name)
{
std::unique_lock<std::mutex> lock(_mutex);
auto it = _services.find(method_name);
if (it == _services.end())
{
return ServiceDescribe::ptr();
}
return it->second;
}
// 移除一个服务
void remove(const std::string &method_name)
{
std::unique_lock<std::mutex> lock(_mutex);
_services.erase(method_name);
}
private:
std::mutex _mutex;
std::unordered_map<std::string, ServiceDescribe::ptr> _services;
};
class RpcRouter
{
public:
using ptr = std::shared_ptr<RpcRouter>;
RpcRouter()
: _service_manager(std::make_shared<ServiceManager>())
{}
// 这个函数会注册到Dispatcher模块,是服务端针对收到一条Rpc请求进行回调处理的业务函数
void onRpcRequest(const BaseConnection::ptr& conn, RpcRequest::ptr& request)
{
// 1.查询客户端请求的方法是否存在
auto service = _service_manager->select(request->method());
if(service.get() == nullptr)
{
LOG(LogLevel::INFO) << "当前服务未找到: " << request->method();
response(conn, request, Json::Value(), RCode::RCODE_NOT_FOUND_SERVICE);
return;
}
// 2.校验请求中的参数是否符合服务要求
if(service->paramCheck(request->params()) == false)
{
LOG(LogLevel::INFO) << "当前服务参数校验失败: " << request->method();
response(conn, request, Json::Value(), RCode::RCODE_INVALID_PARAMS);
return;
}
// 3.调用业务回调接口进行处理
Json::Value result;
bool ret = service->call(request->params(), result);
if(ret == false)
{
LOG(LogLevel::INFO) << "当前服务内部失败: " << request->method();
response(conn, request, Json::Value(), RCode::RCODE_INTERNAL_ERROR);
return;
}
// 4.处理完毕得到结果,组织响应向客户端发送
response(conn, request, result, RCode::RCODE_OK);
}
void registerMethod(const ServiceDescribe::ptr& service)
{
_service_manager->insert(service);
}
private:
void response(const BaseConnection::ptr& conn, const RpcRequest::ptr& req, const Json::Value &res, RCode rcode)
{
auto msg = MsgFactory::create<RpcResponse>();
msg->setId(req->rid());
msg->setMsgtype(MsgType::RSP_RPC);
msg->setRCode(rcode);
msg->setResult(res);
conn->send(msg);
}
private:
ServiceManager::ptr _service_manager;
};
}
}
5. Registry-Discovery模块
该模块针对服务注册与发现请求的处理。
cpp
// server---DiscoverRegistry.hpp
#pragma once
#include "../common/net.hpp"
#include "../common/message.hpp"
#include <memory>
#include <mutex>
#include <set>
#include <vector>
#include <unordered_map>
namespace RPC
{
namespace server
{
class ProviderManager
{
public:
using ptr = std::shared_ptr<ProviderManager>;
struct Provider
{
using ptr = std::shared_ptr<Provider>;
std::mutex mutex;
BaseConnection::ptr conn;
Address host;
std::vector<std::string> methods;
Provider(const BaseConnection::ptr& c, const Address& h)
: conn(c), host(h)
{}
void appendMethod(const std::string& method)
{
std::unique_lock<std::mutex> lock(mutex);
methods.emplace_back(method);
}
};
// 一个服务提供者, 注册一个新服务时调用
void addProvider(const BaseConnection::ptr& c, const Address& h, const std::string method)
{
Provider::ptr provider;
// 查找当前服务提供者是否已存在,找到则获取; 找不到则新建映射,并建立关联
{
std::unique_lock<std::mutex> lock(_mutex);
auto it = _conns.find(c);
if(it == _conns.end())
{
provider = std::make_shared<Provider>(c, h);
_conns.insert(std::make_pair(c, provider));
}
else
{
provider = it->second;
}
_providers[method].insert(provider);
}
provider->appendMethod(method);
}
// 当一个服务提供者断开连接时,需要知道他的信息,以便对他提供的服务的发现者做下线通知
Provider::ptr getProvider(const BaseConnection::ptr& c)
{
std::unique_lock<std::mutex> lock(_mutex);
auto it = _conns.find(c);
if(it == _conns.end())
{
return Provider::ptr();
}
return it->second;
}
// 当一个服务提供者断开连接时,删除它的关联信息
void delProvider(const BaseConnection::ptr& c)
{
std::unique_lock<std::mutex> lock(_mutex);
auto it = _conns.find(c);
if(it == _conns.end())
{
return;
}
// 找这个服务提供者提供的所有服务,从服务提供者表中删除当前服务提供者
for(auto& method : it->second->methods)
{
_providers[method].erase(it->second);
}
// 从连接映射表中删除该连接
_conns.erase(it);
}
// 获取一个服务的所有提供者主机地址
std::vector<Address> methodHosts(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& provider : it->second)
{
ret.push_back(provider->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; // <一个连接---对应的提供者>
};
class DiscovererManager
{
public:
using ptr = std::shared_ptr<DiscovererManager>;
struct Discoverer
{
using ptr = std::shared_ptr<Discoverer>;
std::mutex mutex;
BaseConnection::ptr conn; // 发现者关联的客户端连接
std::vector<std::string> methods; // 发现过的服务名称
Discoverer(const BaseConnection::ptr& c)
: conn(c)
{}
void appendMethod(const std::string& method)
{
std::unique_lock<std::mutex> lock(mutex);
methods.emplace_back(method);
}
};
// 一个服务发现者, 发现一个服务时调用
Discoverer::ptr addDiscoverer(const BaseConnection::ptr& c, const std::string& method)
{
Discoverer::ptr discoverer;
{
std::unique_lock<std::mutex> lock(_mutex);
auto it = _conns.find(c);
if(it == _conns.end())
{
discoverer = std::make_shared<Discoverer>(c);
_conns.insert(std::make_pair(c, discoverer));
}
else
{
discoverer = it->second;
}
_discoverers[method].insert(discoverer);
}
discoverer->appendMethod(method);
return discoverer;
}
//发现者客户端断开连接时,找到发现者信息,删除关联数据
void delDiscoverer(const BaseConnection::ptr &c)
{
std::unique_lock<std::mutex> lock(_mutex);
auto it = _conns.find(c);
if(it == _conns.end())
{
return;
}
for(auto& method : it->second->methods)
{
_discoverers[method].erase(it->second);
}
_conns.erase(it);
}
void onlineNotify(const std::string& method, const Address& host)
{
notify(method, host, ServiceOpType::SERVICE_ONLINE);
}
void offlineNotify(const std::string& method, const Address& host)
{
notify(method, host, ServiceOpType::SERVICE_OFFLINE);
}
private:
// 组织一条服务上线/下线的服务请求消息,发送给每个这个服务的发现者
void notify(const std::string& method, const Address& host, ServiceOpType optype)
{
std::unique_lock<std::mutex> lock(_mutex);
auto it = _discoverers.find(method);
if(it == _discoverers.end()) // 代表这个服务没有发现者
{
return;
}
auto msg_req = MsgFactory::create<ServiceRequest>();
msg_req->setId(UUID::uuid());
msg_req->setMsgtype(MsgType::REQ_SERVICE);
msg_req->setOptype(optype);
msg_req->setMethod(method);
msg_req->setHost(host);
for(auto& discover : it->second)
{
discover->conn->send(msg_req);
}
}
private:
std::mutex _mutex;
std::unordered_map<std::string, std::set<Discoverer::ptr>> _discoverers; // <一个服务---所有它的发现者>
std::unordered_map<BaseConnection::ptr, Discoverer::ptr> _conns; // <一个连接---对应的发现者>
};
class PDManager
{
public:
using ptr = std::shared_ptr<PDManager>;
PDManager()
: _providers(std::make_shared<ProviderManager>())
, _discoverers(std::make_shared<DiscovererManager>())
{}
// 这个函数会注册到注册中心服务端dispatcher模块,是针对服务请求类型消息(服务注册/服务发现)的业务回调函数
void onServiceMessgage(const BaseConnection::ptr& conn, const ServiceRequest::ptr& msg)
{
ServiceOpType optype = msg->optype();
if(optype == ServiceOpType::SERVICE_REGISTRY)
{
LOG(LogLevel::INFO) << msg->host().first << ":" << msg->host().second << "注册服务" << msg->method();
_providers->addProvider(conn, msg->host(), msg->method());
_discoverers->onlineNotify(msg->method(), msg->host());
registryResponse(conn, msg);
}
else if(optype == ServiceOpType::SERVICE_DISCOVERY)
{
LOG(LogLevel::INFO) << msg->host().first << ":" << msg->host().second << "要发现服务" << msg->method();
_discoverers->addDiscoverer(conn, msg->method());
discoveryResponse(conn, msg);
}
else
{
LOG(LogLevel::ERROR) << "收到服务操作请求,但是操作类型错误!";
errorResponse(conn, msg);
}
}
// 这个函数会设置到连接关闭时的回调函数中
void onConnShutdown(const BaseConnection::ptr& conn)
{
auto provider = _providers->getProvider(conn);
if (provider.get() != nullptr)
{
LOG(LogLevel::INFO) << provider->host.first << ":" << provider->host.second << "服务下线";
for (auto& method : provider->methods)
{
_discoverers->offlineNotify(method, provider->host);
}
_providers->delProvider(conn);
}
_discoverers->delDiscoverer(conn);
}
private:
void errorResponse(const BaseConnection::ptr& conn, const ServiceRequest::ptr& msg)
{
auto msg_rsp = MsgFactory::create<ServiceResponse>();
msg_rsp->setId(msg->rid());
msg_rsp->setMsgtype(MsgType::RSP_SERVICE);
msg_rsp->setRCode(RCode::RCODE_INVALID_OPTYPE);
msg_rsp->setOptype(ServiceOpType::SERVICE_UNKNOW);
conn->send(msg_rsp);
}
// 服务注册的响应信息,正文只需要包含结果是否成功即可
void registryResponse(const BaseConnection::ptr& conn, const ServiceRequest::ptr& msg)
{
auto msg_rsp = MsgFactory::create<ServiceResponse>();
msg_rsp->setId(msg->rid());
msg_rsp->setMsgtype(MsgType::RSP_SERVICE);
msg_rsp->setRCode(RCode::RCODE_OK);
msg_rsp->setOptype(ServiceOpType::SERVICE_REGISTRY);
conn->send(msg_rsp);
}
// 服务发现的响应信息,正文中还需包含服务的提供者都有哪些主机
void discoveryResponse(const BaseConnection::ptr& conn, const ServiceRequest::ptr& msg)
{
auto msg_rsp = MsgFactory::create<ServiceResponse>();
msg_rsp->setId(msg->rid());
msg_rsp->setMsgtype(MsgType::RSP_SERVICE);
msg_rsp->setOptype(ServiceOpType::SERVICE_DISCOVERY);
std::vector<Address> hosts = _providers->methodHosts(msg->method());
if (hosts.empty())
{
msg_rsp->setRCode(RCode::RCODE_NOT_FOUND_SERVICE);
return conn->send(msg_rsp);
}
msg_rsp->setRCode(RCode::RCODE_OK);
msg_rsp->setMethod(msg->method());
msg_rsp->setHost(hosts);
return conn->send(msg_rsp);
}
private:
ProviderManager::ptr _providers;
DiscovererManager::ptr _discoverers;
};
}
}
cpp
// client---DiscoverRegistry.hpp
#pragma once
#include "Requestor.hpp"
#include <memory>
namespace RPC
{
namespace client
{
class Provider
{
public:
using ptr = std::shared_ptr<Provider>;
Provider(const Requestor::ptr &requestor)
: _requestor(requestor)
{}
bool registerMethod(const BaseConnection::ptr& conn, const std::string& method, const Address& host)
{
auto msg_req = MsgFactory::create<ServiceRequest>();
msg_req->setId(UUID::uuid());
msg_req->setMsgtype(MsgType::REQ_SERVICE);
msg_req->setMethod(method);
msg_req->setHost(host);
msg_req->setOptype(ServiceOpType::SERVICE_REGISTRY);
BaseMessage::ptr msg_rsp;
bool ret = _requestor->send(conn, msg_req, msg_rsp);
if(ret == false)
{
LOG(LogLevel::ERROR) << method << "服务注册失败!";
return false;
}
auto service_rsp = std::dynamic_pointer_cast<ServiceResponse>(msg_rsp);
if(service_rsp.get() == nullptr)
{
LOG(LogLevel::ERROR) << "响应类型向下转换失败!";
return false;
}
if (service_rsp->rcode() != RCode::RCODE_OK)
{
LOG(LogLevel::ERROR) << "服务注册失败!" << errReason(service_rsp->rcode());
return false;
}
return true;
}
private:
Requestor::ptr _requestor;
};
class Discoverer
{
public:
using ptr = std::shared_ptr<Discoverer>;
using OfflineCallback = std::function<void(const Address&)>;
Discoverer(const Requestor::ptr &requestor, const OfflineCallback &cb)
: _requestor(requestor), _offline_callback(cb)
{}
// 服务发现函数,如果当前的_method_hosts中存在该服务并且有能提供服务的主机,选择一个。如果没有,则发起一次服务发现请求
bool serviceDiscover(const BaseConnection::ptr& conn, const std::string& method, Address& host)
{
{
std::unique_lock<std::mutex> lock(_mutex);
auto it = _method_hosts.find(method);
if(it != _method_hosts.end())
{
if(it->second->empty() == false)
{
host = it->second->chooseHost();
return true;
}
}
}
// 当前没有能提供服务的主机,向注册中心发现一次服务发现请求
auto msg_req = MsgFactory::create<ServiceRequest>();
msg_req->setId(UUID::uuid());
msg_req->setMsgtype(MsgType::REQ_SERVICE);
msg_req->setMethod(method);
msg_req->setOptype(ServiceOpType::SERVICE_DISCOVERY);
BaseMessage::ptr msg_rsp;
bool ret = _requestor->send(conn, msg_req, msg_rsp);
if(ret == false)
{
LOG(LogLevel::ERROR) << "服务发现请求失败!";
return false;
}
auto service_rsp = std::dynamic_pointer_cast<ServiceResponse>(msg_rsp);
if(service_rsp.get() == nullptr)
{
LOG(LogLevel::ERROR) << "服务发现响应类型向下转换失败!";
return false;
}
if (service_rsp->rcode() != RCode::RCODE_OK)
{
LOG(LogLevel::ERROR) << "服务发现失败!" << errReason(service_rsp->rcode());
return false;
}
{
std::unique_lock<std::mutex> lock(_mutex);
auto method_host = std::make_shared<MethodHost>(service_rsp->hosts());
if(method_host->empty())
{
// 说明注册中心中,这个服务就没有提供者
LOG(LogLevel::INFO) << method << "服务发现失败! 没有能提供该服务的主机!";
return false;
}
host = method_host->chooseHost();
_method_hosts[method] = method_host;
return true;
}
}
// 这个函数要注册到dispatcher模块,服务发现客户端针对服务上下线请求处理的回调函数
void onServiceRequest(const BaseConnection::ptr& conn, const ServiceRequest::ptr& msg)
{
auto optype = msg->optype();
std::string method = msg->method();
std::unique_lock<std::mutex> lock(_mutex);
if (optype == ServiceOpType::SERVICE_ONLINE)
{
// 如果是上线请求:找到MethodHost,向其中新增一个主机地址
auto it = _method_hosts.find(method);
if (it == _method_hosts.end())
{
auto method_host = std::make_shared<MethodHost>();
method_host->appendHost(msg->host());
_method_hosts[method] = method_host;
}
else
{
it->second->appendHost(msg->host());
}
}
else if (optype == ServiceOpType::SERVICE_OFFLINE)
{
// 如果是下线请求:找到MethodHost,从其中删除这个下线的主机地址
auto it = _method_hosts.find(method);
if (it == _method_hosts.end())
{
return;
}
it->second->removeHost(msg->host());
_offline_callback(msg->host());
}
}
private:
class MethodHost
{
public:
using ptr = std::shared_ptr<MethodHost>;
MethodHost() : _idx(0) {}
MethodHost(const std::vector<Address>& hosts) : _hosts(hosts), _idx(0) {}
void appendHost(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 == host)
{
_hosts.erase(it);
break;
}
}
}
// 从一个服务的众多提供者中选择一个,这里采用轮转访问,分散载荷压力
Address chooseHost()
{
std::unique_lock<std::mutex> lock(_mutex);
size_t pos = _idx % _hosts.size();
_idx++;
return _hosts[pos];
};
bool empty()
{
return _hosts.empty();
}
private:
std::mutex _mutex;
size_t _idx;
std::vector<Address> _hosts;
};
private:
OfflineCallback _offline_callback;
std::mutex _mutex;
std::unordered_map<std::string, MethodHost::ptr> _method_hosts;
Requestor::ptr _requestor;
};
}
}
6. Publish-Subscribe模块
该模块针对主题的发布订阅请求进行处理。
cpp
// server---PublishSubscribe.hpp
#pragma once
#include "../common/net.hpp"
#include "../common/message.hpp"
#include <memory>
#include <mutex>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
namespace RPC
{
namespace server
{
class TopicManager
{
public:
using ptr = std::shared_ptr<TopicManager>;
TopicManager(){}
// 这个函数注册到主题中转中心的dispatcher模块,是针对收到一条主题请求的业务回调函数
void onTopicRequest(const BaseConnection::ptr& conn, TopicRequest::ptr& msg)
{
TopicOpType optype = msg->optype();
bool ret = true;
switch(optype)
{
case TopicOpType::TOPIC_CREATE:
topicCreate(conn, msg);
break;
case TopicOpType::TOPIC_REMOVE:
topicRemove(conn, msg);
break;
case TopicOpType::TOPIC_SUBSCRIBE:
ret = topicSubscribe(conn, msg);
break;
case TopicOpType::TOPIC_CANCEL:
topicCancel(conn, msg);
case TopicOpType::TOPIC_PUBLISH:
ret = topicPublish(conn, msg);
break;
default:
errorResponse(conn, msg, RCode::RCODE_INVALID_OPTYPE);
return;
}
if(ret == false)
{
errorResponse(conn, msg, RCode::RCODE_NOT_FOUND_TOPIC);
return;
}
topicResponse(conn, msg);
}
// 一个订阅者在连接断开时的处理,删除其关联的数据
// 发布者断开连接不需要任何操作
void onShutDown(const BaseConnection::ptr& conn)
{
std::vector<Topic::ptr> topics;
Subscriber::ptr subscriber;
{
// 1. 判断断开连接的是否是订阅者,不是的话则直接返回
std::unique_lock<std::mutex> lock(_mutex);
auto it = _subscribers.find(conn);
if(it == _subscribers.end())
{
return;
}
subscriber = it->second;
// 2. 获取断开的订阅者订阅的主题对象
for(auto& topic_name : subscriber->topics)
{
auto topic_it = _topics.find(topic_name);
if(topic_it != _topics.end())
{
topics.push_back(topic_it->second);
}
}
_subscribers.erase(it);
}
// 3.从受影响的主题对象中,移除断开的订阅者信息
for(auto& topic : topics)
{
topic->removeSubsciber(subscriber);
}
}
private:
void errorResponse(const BaseConnection::ptr& conn, const TopicRequest::ptr& msg, RCode rcode)
{
auto msg_rsp = MsgFactory::create<TopicResponse>();
msg_rsp->setId(msg->rid());
msg_rsp->setMsgtype(MsgType::RSP_TOPIC);
msg_rsp->setRCode(rcode);
conn->send(msg_rsp);
}
void topicResponse(const BaseConnection::ptr& conn, const TopicRequest::ptr& msg)
{
auto msg_rsp = MsgFactory::create<TopicResponse>();
msg_rsp->setId(msg->rid());
msg_rsp->setMsgtype(MsgType::RSP_TOPIC);
msg_rsp->setRCode(RCode::RCODE_OK);
conn->send(msg_rsp);
}
void topicCreate(const BaseConnection::ptr& conn, const TopicRequest::ptr& msg)
{
std::unique_lock<std::mutex> lock(_mutex);
std::string topic_name = msg->topicKey();
auto topic = std::make_shared<Topic>(topic_name);
_topics.insert(std::make_pair(topic_name, topic));
}
void topicRemove(const BaseConnection::ptr& conn, const TopicRequest::ptr& msg)
{
// 1. 查看当前主题有哪些订阅者,然后从订阅者中将该主题信息删除掉
// 2. 删除主题的关联数据
std::string topic_name = msg->topicKey();
std::unordered_set<Subscriber::ptr> subscribers;
{
std::unique_lock<std::mutex> lock(_mutex);
auto it = _topics.find(topic_name);
if(it == _topics.end())
{
return;
}
subscribers = it->second->subscribers;
_topics.erase(it);
}
for(auto& sub : subscribers)
{
sub->removeTopic(topic_name);
}
}
bool topicSubscribe(const BaseConnection::ptr& conn, const TopicRequest::ptr& msg)
{
// 1. 先找出主题对象,以及订阅者对象
// 如果没有找到主题--返回错误。但是如果没有找到订阅者对象--就要构造一个订阅者
std::string topic_name = msg->topicKey();
Topic::ptr topic;
Subscriber::ptr subscriber;
{
std::unique_lock<std::mutex> lock(_mutex);
auto it1 = _topics.find(topic_name);
if(it1 == _topics.end())
{
return false;
}
topic = it1->second;
auto it2 = _subscribers.find(conn);
if(it2 == _subscribers.end())
{
subscriber = std::make_shared<Subscriber>(conn);
_subscribers.insert(std::make_pair(conn, subscriber));
}
else
{
subscriber = it2->second;
}
}
// 2. 在主题对象中新增一个订阅者对象关联的连接,在订阅者对象中新增一个订阅主题
topic->appendSubscribe(subscriber);
subscriber->append(topic_name);
return true;
}
void topicCancel(const BaseConnection::ptr& conn, const TopicRequest::ptr& msg)
{
// 1. 先找出主题对象,以及订阅者对象
std::string topic_name = msg->topicKey();
Topic::ptr topic;
Subscriber::ptr subscriber;
{
std::unique_lock<std::mutex> lock(_mutex);
auto it1 = _topics.find(topic_name);
if (it1 != _topics.end())
{
topic = it1->second;
}
auto it2 = _subscribers.find(conn);
if (it2 != _subscribers.end())
{
subscriber = it2->second;
}
}
// 2. 从主题对象中删除当前的订阅者。从订阅者信息中删除订阅主题
if (subscriber)
{
subscriber->removeTopic(topic_name);
}
if (topic && subscriber)
{
topic->removeSubsciber(subscriber);
}
}
bool topicPublish(const BaseConnection::ptr& conn, const TopicRequest::ptr& msg)
{
Topic::ptr topic;
{
std::unique_lock<std::mutex> lock(_mutex);
auto it = _topics.find(msg->topicKey());
if (it == _topics.end())
{
return false;
}
topic = it->second;
}
topic->broadMessage(msg);
return true;
}
private:
struct Subscriber
{
using ptr = std::shared_ptr<Subscriber>;
std::mutex _mutex;
BaseConnection::ptr conn;
std::unordered_set<std::string> topics; // 一个订阅者的所有订阅主题
Subscriber(const BaseConnection::ptr& c)
: conn(c)
{}
// 订阅主题时调用
void append(const std::string& topic)
{
std::unique_lock<std::mutex> lock(_mutex);
topics.insert(topic);
}
// 主题被删除或取消订阅时调用
void removeTopic(const std::string& topic)
{
std::unique_lock<std::mutex> lock(_mutex);
topics.erase(topic);
}
};
struct Topic
{
using ptr = std::shared_ptr<Topic>;
std::mutex _mutex;
std::string topic_name;
std::unordered_set<Subscriber::ptr> subscribers; // 一个主题的所有订阅者
Topic(const std::string& topic)
: topic_name(topic)
{}
// 一个主题新增被订阅者时调用
void appendSubscribe(const Subscriber::ptr& subscriber)
{
std::unique_lock<std::mutex> lock(_mutex);
subscribers.insert(subscriber);
}
// 一个主题被取消订阅或订阅者连接断开时调用
void removeSubsciber(const Subscriber::ptr& subscriber)
{
std::unique_lock<std::mutex> lock(_mutex);
subscribers.erase(subscriber);
}
// 收到消息发布请求时调用: 广播通知
void broadMessage(const BaseMessage::ptr& msg)
{
std::unique_lock<std::mutex> lock(_mutex);
for(auto& subscriber : subscribers)
{
subscriber->conn->send(msg);
}
}
};
private:
std::mutex _mutex;
std::unordered_map<std::string, Topic::ptr> _topics;
std::unordered_map<BaseConnection::ptr, Subscriber::ptr> _subscribers;
};
}
}
cpp
// client---PublishSubscribe.hpp
#pragma once
#include "../common/net.hpp"
#include "../common/message.hpp"
#include "Requestor.hpp"
#include <memory>
#include <string>
#include <utility>
namespace RPC
{
namespace client
{
class TopicManager
{
public:
using ptr = std::shared_ptr<TopicManager>;
using SubCallback = std::function<void(const std::string& key, const std::string& msg)>;
TopicManager(const Requestor::ptr& req)
: _requestor(req)
{}
bool createTopic(const BaseConnection::ptr& conn, const std::string& key)
{
return commonRequest(conn, key, TopicOpType::TOPIC_CREATE);
}
bool removeTopic(const BaseConnection::ptr& conn, const std::string& key)
{
return commonRequest(conn, key, TopicOpType::TOPIC_REMOVE);
}
bool subscribe(const BaseConnection::ptr& conn, const std::string& key, const SubCallback& cb)
{
addSubscribe(key, cb);
bool ret = commonRequest(conn, key, TopicOpType::TOPIC_SUBSCRIBE);
if (ret == false)
{
delSubscribe(key);
return false;
}
return true;
}
bool cancel(const BaseConnection::ptr& conn, const std::string& key)
{
delSubscribe(key);
return commonRequest(conn, key, TopicOpType::TOPIC_CANCEL);
}
bool publish(const BaseConnection::ptr& conn, const std::string& key, const std::string& msg)
{
return commonRequest(conn, key, TopicOpType::TOPIC_PUBLISH, msg);
}
// 这个函数要注册到主题订阅端的dispatcher模块,针对主题消息发布类型的请求的业务回调函数
void onPublish(const BaseConnection::ptr& conn, const TopicRequest::ptr& msg)
{
if(msg->optype() != TopicOpType::TOPIC_PUBLISH)
{
LOG(LogLevel::ERROR) << "收到了错误类型的主题请求操作!";
return;
}
std::string key = msg->topicKey();
std::string topic_msg = msg->topicMsg();
auto callback = getSubcribe(key);
if(!callback)
{
LOG(LogLevel::ERROR) << "收到了主题消息发布请求操作,但是没有处理回调函数!";
return;
}
callback(key, topic_msg);
}
private:
void addSubscribe(const std::string& key, const SubCallback& cb)
{
std::unique_lock<std::mutex> lock(_mutex);
_topic_callbacks.insert(std::make_pair(key, cb));
}
void delSubscribe(const std::string& key)
{
std::unique_lock<std::mutex> lock(_mutex);
_topic_callbacks.erase(key);
}
const SubCallback getSubcribe(const std::string& key)
{
std::unique_lock<std::mutex> lock(_mutex);
auto it = _topic_callbacks.find(key);
if(it == _topic_callbacks.end())
{
return SubCallback();
}
return it->second;
}
bool commonRequest(const BaseConnection::ptr& conn, const std::string& key, TopicOpType type, const std::string& msg = "")
{
//1. 构造请求对象,并填充数据
auto msg_req = MsgFactory::create<TopicRequest>();
msg_req->setId(UUID::uuid());
msg_req->setMsgtype(MsgType::REQ_TOPIC);
msg_req->setTopicKey(key);
msg_req->setOptype(type);
if(type == TopicOpType::TOPIC_PUBLISH)
{
msg_req->setTopicMsg(msg);
}
//2. 向服务端发送请求,等待响应
BaseMessage::ptr msg_rsp;
bool ret = _requestor->send(conn, msg_req, msg_rsp);
if (ret == false)
{
LOG(LogLevel::ERROR) << "主题操作请求失败!";
return false;
}
// 3. 判断请求处理是否成功
auto topic_rsp_msg = std::dynamic_pointer_cast<TopicResponse>(msg_rsp);
if (!topic_rsp_msg)
{
LOG(LogLevel::ERROR) << "主题操作响应,向下类型转换失败!";
return false;
}
if (topic_rsp_msg->rcode() != RCode::RCODE_OK)
{
LOG(LogLevel::ERROR) << "主题操作请求出错: " << errReason(topic_rsp_msg->rcode());
return false;
}
return true;
}
private:
std::mutex _mutex;
std::unordered_map<std::string, SubCallback> _topic_callbacks;
Requestor::ptr _requestor;
};
}
}
7. server模块
将所有功能整合到一起来实现服务端程序。
RpcServer:rpc功能模块与网络通信部分结合。
RegistryServer:服务发现注册功能模块与网络通信部分结合,作为注册中心
TopicServer:发布订阅功能模块与网络通信部分结合。
cpp
// server.hpp
#pragma once
#include "../common/dispatcher.hpp"
#include "../client/client.hpp"
#include "RpcRouter.hpp"
#include "DiscoverRegistry.hpp"
#include "PublishSubscribe.hpp"
#include <memory>
namespace RPC
{
namespace server
{
// 服务注册中心 服务端
// 只需要针对服务注册与发现请求进行处理即可
class RegistryServer
{
public:
using ptr = std::shared_ptr<RegistryServer>;
RegistryServer(int port)
: _pd_manager(std::make_shared<PDManager>())
, _dispatcher(std::make_shared<Dispatcher>())
, _server(ServerFactory::create(port))
{
auto service_cb = std::bind(&PDManager::onServiceMessgage, _pd_manager.get(), std::placeholders::_1, std::placeholders::_2);
_dispatcher->registerHandler<ServiceRequest>(MsgType::REQ_SERVICE, service_cb);
auto message_cb = std::bind(&Dispatcher::onMessage, _dispatcher.get(), std::placeholders::_1, std::placeholders::_2);
_server->setMessageCallBack(message_cb);
auto close_cb = std::bind(&RegistryServer::onConnShutdown, this, std::placeholders::_1);
_server->setCloseCallBack(close_cb);
}
void start()
{
_server->start();
}
private:
void onConnShutdown(const BaseConnection::ptr& conn)
{
_pd_manager->onConnShutdown(conn);
}
private:
PDManager::ptr _pd_manager;
Dispatcher::ptr _dispatcher;
BaseServer::ptr _server;
};
// Rpc服务注册方法提供端,封装服务注册客户端
class RpcServer
{
public:
using ptr = std::shared_ptr<RpcServer>;
// rpc服务端有两套地址信息:
// 1. rpc服务提供端地址信息--必须是rpc服务器对外访问地址,但是这里云服务器的监听地址和访问地址不同
// 2. 注册中心服务端地址信息--启用服务注册后,连接注册中心进行服务注册用的
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>())
, _server(ServerFactory::create(access_addr.second))
{
if (enableRegistry)
{
_reg_client = std::make_shared<client::RegistryClient>(registry_server_addr.first, registry_server_addr.second);
}
auto rpc_cb = std::bind(&RpcRouter::onRpcRequest, _router.get(), std::placeholders::_1, std::placeholders::_2);
_dispatcher->registerHandler<RpcRequest>(MsgType::REQ_RPC, rpc_cb);
auto message_cb = std::bind(&Dispatcher::onMessage, _dispatcher.get(), std::placeholders::_1, std::placeholders::_2);
_server->setMessageCallBack(message_cb);
}
void registerMethod(const ServiceDescribe::ptr& service)
{
if (_enableRegistry)
{
_reg_client->registerMethod(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; //成员_server是一个rpcserver,用于提供rpc服务的
};
// 主题消息中转中心,服务端
class TopicServer
{
public:
using ptr = std::shared_ptr<TopicServer>;
TopicServer(int port)
: _topic_manager(std::make_shared<TopicManager>())
, _dispatcher(std::make_shared<Dispatcher>())
, _server(ServerFactory::create(port))
{
auto topic_cb = std::bind(&TopicManager::onTopicRequest, _topic_manager.get(), std::placeholders::_1, std::placeholders::_2);
_dispatcher->registerHandler<TopicRequest>(MsgType::REQ_TOPIC, topic_cb);
auto message_cb = std::bind(&Dispatcher::onMessage, _dispatcher.get(), std::placeholders::_1, std::placeholders::_2);
_server->setMessageCallBack(message_cb);
auto close_cb = std::bind(&TopicServer::onConnShutdown, this, std::placeholders::_1);
_server->setCloseCallBack(close_cb);
}
void start()
{
_server->start();
}
private:
void onConnShutdown(const BaseConnection::ptr& conn)
{
_topic_manager->onShutDown(conn);
}
private:
TopicManager::ptr _topic_manager;
Dispatcher::ptr _dispatcher;
BaseServer::ptr _server;
};
}
}
8. client模块
将以上模块进行整合就可以实现各个功能的客户端了。
RegistryClient:服务注册功能模块与网络通信客户端结合,服务提供客户端
DiscoveryClient:服务发现功能模块与网络通信客户端结合,服务发现客户端
RpcClient:DiscoveryClient + RPC功能模块与网络通信客户端结合
TopicClient:发布订阅功能模块与网络通信客户端结合
cpp
// client.hpp
#pragma once
#include "../common/dispatcher.hpp"
#include "Requestor.hpp"
#include "RpcCaller.hpp"
#include "DiscoverRegistry.hpp"
#include "PublishSubscribe.hpp"
namespace RPC
{
namespace client
{
// 服务注册客户端
class RegistryClient
{
public:
using ptr = std::shared_ptr<RegistryClient>;
//构造函数传入注册中心的地址信息,用于连接注册中心
RegistryClient(const std::string& ip, int port)
: _requestor(std::make_shared<Requestor>())
, _provider(std::make_shared<client::Provider>(_requestor))
, _dispatcher(std::make_shared<Dispatcher>())
, _client(ClientFactory::create(ip, port))
{
auto rsp_cb = std::bind(&client::Requestor::onResponse, _requestor.get(), std::placeholders::_1, std::placeholders::_2);
_dispatcher->registerHandler<BaseMessage>(MsgType::RSP_SERVICE, rsp_cb);
auto message_cb = std::bind(&Dispatcher::onMessage, _dispatcher.get(), std::placeholders::_1, std::placeholders::_2);
_client->setMessageCallBack(message_cb);
_client->connect();
}
// 向外提供的服务注册接口
bool registerMethod(const std::string& method, const Address& host)
{
return _provider->registerMethod(_client->connection(), method, host);
}
private:
Requestor::ptr _requestor;
client::Provider::ptr _provider;
Dispatcher::ptr _dispatcher;
BaseClient::ptr _client;
};
// 服务发现客户端
class DiscoveryClient
{
public:
using ptr = std::shared_ptr<DiscoveryClient>;
//构造函数传入注册中心的地址信息,用于连接注册中心。同时需要提供服务提供者下线时的处理方法
DiscoveryClient(const std::string& ip, int port, const Discoverer::OfflineCallback& cb)
: _requestor(std::make_shared<Requestor>())
, _discoverer(std::make_shared<client::Discoverer>(_requestor, cb))
, _dispatcher(std::make_shared<Dispatcher>())
, _client(ClientFactory::create(ip, port))
{
auto rsp_cb = std::bind(&client::Requestor::onResponse, _requestor.get(), std::placeholders::_1, std::placeholders::_2);
_dispatcher->registerHandler<BaseMessage>(MsgType::RSP_SERVICE, rsp_cb);
auto req_cb = std::bind(&client::Discoverer::onServiceRequest, _discoverer.get(), std::placeholders::_1, std::placeholders::_2);
_dispatcher->registerHandler<ServiceRequest>(MsgType::REQ_SERVICE, req_cb);
auto message_cb = std::bind(&Dispatcher::onMessage, _dispatcher.get(), std::placeholders::_1, std::placeholders::_2);
_client->setMessageCallBack(message_cb);
_client->connect();
}
//向外提供的服务发现接口
bool serviceDiscovery(const std::string& method, Address& host)
{
return _discoverer->serviceDiscover(_client->connection(), method, host);
}
private:
Requestor::ptr _requestor;
client::Discoverer::ptr _discoverer;
Dispatcher::ptr _dispatcher;
BaseClient::ptr _client;
};
// Rpc调用客户端
class RpcClient
{
public:
using ptr = std::shared_ptr<RpcClient>;
// enableDiscovery--是否启用服务发现功能,也决定了传入的地址信息是注册中心的地址,还是服务提供者的地址
RpcClient(bool enableDiscovery, const std::string& ip, int port)
: _enableDiscovery(enableDiscovery)
, _requestor(std::make_shared<Requestor>())
, _dispatcher(std::make_shared<Dispatcher>())
, _caller(std::make_shared<client::RpcCaller>(_requestor))
{
auto rsp_cb = std::bind(&client::Requestor::onResponse, _requestor.get(), std::placeholders::_1, std::placeholders::_2);
_dispatcher->registerHandler<BaseMessage>(MsgType::RSP_RPC, rsp_cb);
//如果启用了服务发现,传入地址是注册中心的地址,是服务发现客户端需要连接的地址,则通过地址信息实例化_discovery_client
//如果没有启用服务发现,则传入地址信息是服务提供者的地址,则直接实例化好_rpc_client
if (_enableDiscovery)
{
auto offline_cb = std::bind(&RpcClient::delClient, this, std::placeholders::_1);
_discovery_client = std::make_shared<DiscoveryClient>(ip, port, offline_cb);
}
else
{
auto message_cb = std::bind(&Dispatcher::onMessage, _dispatcher.get(), std::placeholders::_1, std::placeholders::_2);
_rpc_client = ClientFactory::create(ip, port);
_rpc_client->setMessageCallBack(message_cb);
_rpc_client->connect();
}
}
// 同步方式调用
bool call(const std::string& method, const Json::Value& params, Json::Value& result)
{
BaseClient::ptr client = getClient(method);
if(client.get() == nullptr)
{
return false;
}
return _caller->call(client->connection(), method, params, result);
}
// 异步方式调用
bool call(const std::string& method, const Json::Value& params, RpcCaller::JsonAsyncResponse& result)
{
BaseClient::ptr client = getClient(method);
if(client.get() == nullptr)
{
return false;
}
return _caller->call(client->connection(), method, params, result);
}
// 回调函数方式调用
bool call(const std::string& method, const Json::Value& params, const RpcCaller::JsonResponseCallback& cb)
{
BaseClient::ptr client = getClient(method);
if (client.get() == nullptr)
{
return false;
}
return _caller->call(client->connection(), method, params, cb);
}
private:
BaseClient::ptr newClient(const Address& host)
{
auto message_cb = std::bind(&Dispatcher::onMessage, _dispatcher.get(), std::placeholders::_1, std::placeholders::_2);
auto client = ClientFactory::create(host.first, host.second);
client->setMessageCallBack(message_cb);
client->connect();
putClient(host, client);
return client;
}
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 BaseClient::ptr();
}
return it->second;
}
BaseClient::ptr getClient(const std::string method)
{
BaseClient::ptr client;
if (_enableDiscovery)
{
// 1. 通过服务发现,获取服务提供者地址信息
Address host;
bool ret = _discovery_client->serviceDiscovery(method, host);
if (ret == false)
{
LOG(LogLevel::INFO) << "当前" << method << "服务,没有找到服务提供者!";
return BaseClient::ptr();
}
// 2. 查看服务提供者是否已有实例化客户端,有则直接使用,没有则创建
client = getClient(host);
if (client.get() == nullptr)
{
client = newClient(host);
}
}
else
{
client = _rpc_client;
}
return client;
}
void putClient(const Address& host, 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 AddressHash
{
size_t operator()(const Address& host) const
{
std::string addr = host.first + std::to_string(host.second);
return std::hash<std::string>{}(addr);
}
};
bool _enableDiscovery;
DiscoveryClient::ptr _discovery_client;
Requestor::ptr _requestor;
RpcCaller::ptr _caller;
Dispatcher::ptr _dispatcher;
std::mutex _mutex;
BaseClient::ptr _rpc_client; // 用于未启用服务发现
std::unordered_map<Address, BaseClient::ptr, AddressHash> _rpc_clients; // 用于启用服务发现的客户端连接池
};
// 主题操作客户端
class TopicClient
{
public:
using ptr = std::shared_ptr<TopicClient>;
TopicClient(const std::string& ip, int port)
: _requestor(std::make_shared<Requestor>())
, _dispatcher(std::make_shared<Dispatcher>())
, _topic_manager(std::make_shared<TopicManager>(_requestor))
, _rpc_client(ClientFactory::create(ip, port))
{
auto rsp_cb = std::bind(&Requestor::onResponse, _requestor.get(), std::placeholders::_1, std::placeholders::_2);
_dispatcher->registerHandler<BaseMessage>(MsgType::RSP_TOPIC, rsp_cb);
auto msg_cb = std::bind(&TopicManager::onPublish, _topic_manager.get(), std::placeholders::_1, std::placeholders::_2);
_dispatcher->registerHandler<TopicRequest>(MsgType::REQ_TOPIC, msg_cb);
auto message_cb = std::bind(&Dispatcher::onMessage, _dispatcher.get(), std::placeholders::_1, std::placeholders::_2);
_rpc_client->setMessageCallBack(message_cb);
_rpc_client->connect();
}
bool createTopic(const std::string& key)
{
return _topic_manager->createTopic(_rpc_client->connection(), key);
}
bool removeTopic(const std::string& key)
{
return _topic_manager->removeTopic(_rpc_client->connection(), key);
}
bool subscribe(const std::string& key, const TopicManager::SubCallback& cb)
{
return _topic_manager->subscribe(_rpc_client->connection(), key, cb);
}
bool cancel(const std::string& key)
{
return _topic_manager->cancel(_rpc_client->connection(), key);
}
bool publish(const std::string& key, const std::string& msg)
{
return _topic_manager->publish(_rpc_client->connection(), key, msg);
}
void shutdown()
{
_rpc_client->shutdown();
}
private:
Requestor::ptr _requestor;
TopicManager::ptr _topic_manager;
Dispatcher::ptr _dispatcher;
BaseClient::ptr _rpc_client;
};
}
}