【项目】JsonRpc框架——开发实现2(业务层)

文章目录

  • 一、业务层的实现
    • [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;
        };
    }
}
相关推荐
前端不太难1 小时前
大模型之后,谁在决定AI的真实速度?
人工智能·状态模式
染指11101 小时前
19.LangChain框架7-LangChain1.0版本使用Agent(中间件实例)
人工智能·python·机器学习·langchain·agent·rag
Shadow(⊙o⊙)1 小时前
mkfifo()命名管道-FIFO客户端 服务端模拟。*System V消息队列、信号量(信号灯)。
linux·运维·服务器·开发语言·c++
daad7771 小时前
继续记录SITL的大循环
linux
h_a_o777oah1 小时前
2026 蓝桥杯软件 C++B组 国赛比赛经历及备赛建议
c++·经验分享·算法·蓝桥杯
孟俊宇-MJY1 小时前
CSDN AI数字营销内容创作功能测评
大数据·人工智能
SHARK_pssm1 小时前
【数据结构——单链表】
数据结构·经验分享·笔记
网络研究院1 小时前
AI安全格局:前沿模型、智能体AI和AI编码工具如何重塑网络安全与关键基础设施韧性
网络·人工智能·安全·模型·威胁
装不满的克莱因瓶1 小时前
从梯度下降到 Adam 优化器:掌握神经网络参数优化的核心原理
人工智能·python·深度学习·神经网络·机器学习·计算机视觉·ai