• RpcProvider的网络服务,以及怎么发布服务方法


    网络模块的设计

    RpcProvider类的设计:

    // 框架提供的专门服务发布rpc服务的网络对象类
    class RpcProvider
    {
    public:
        // 启动rpc服务结点,开始提供rpc远程网络调用服务
        void Run();
    
    private:
        // 组合EventLoop
        muduo::net::EventLoop m_eventLoop;
    
        // 新的socket连接回调
        void OnConnection(const muduo::net::TcpConnectionPtr&);
    
        // 已建立连接用户的读写事件操作
        void OnMessage(const muduo::net::TcpConnectionPtr&, muduo::net::Buffer*, muduo::Timestamp);
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    启动方法的实现

    // 启动rpc服务结点,开始提供rpc远程网络调用服务
    void RpcProvider::Run()
    {
        std::string ip = MprpcApplication::GetInstance().GetConfig().Load("rpcserverip");
        uint16_t port = atoi(MprpcApplication::GetInstance().GetConfig().Load("rpcserverport").c_str());
        muduo::net::InetAddress address(ip, port);
    
        // 创建TcpServer对象
        muduo::net::TcpServer server(&m_eventLoop, address, "RpcProvider");
    
        // 绑定连接回调和消息读写回调方法  分离了网络代码和业务代码
        server.setConnectionCallback(std::bind(&RpcProvider::OnConnection, this, std::placeholders::_1));
        server.setMessageCallback(std::bind(&RpcProvider::OnMessage, this, std::placeholders::_1,
                                    std::placeholders::_2, std::placeholders::_3));
        // 设置muduo库的线程数量
        server.setThreadNum(4);
    
        // 显示信息
        std::cout << "RpcProvider start service at ip: " << ip << "port: " << port << std::endl;
    
        // 启动网络服务
        server.start();
        m_eventLoop.loop();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    那目前实现的功能除了初始化rpc框架和加载配置文件,还设计一个类RpcProvider,实现了框架的网络模块,RpcProvider还需要有提供服务方法:NotifyService()

    在这里插入图片描述

    再来看请求过程:
    如果有请求从网络上发送过来

    在这里插入图片描述

    本地的方法会从中得到请求的参数,执行本地服务,然后把响应response填写好,执行回调操作返回。
    在这里插入图片描述

    那么问题就是,当接收到一个rpc调用请求时,如何知道要调用哪个应用程序的哪个rpc方法呢?

    首先的思路是,我们需要一个表,来记录当前节点的服务对象和服务方法信息。

    NotifyService的实现

    由于rpc方法的实现是通过继承Service类的的派生类实现的,所以需要一个参数:
    google::protobuf::Service。

    然后要设计一个结构体,来记录方法,所需要知道的信息:

    service_name -> service描述 -> service* 记录服务对象 -> method_name -> method方法描述

     // service服务类型信息
        struct ServiceInfo
        {
            google::protobuf::Service* m_service; // 保存服务对象
            std::unordered_map<std::string, const google::protobuf::MethodDescriptor*> m_methodMap; // 保存服务方法
        };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    // 存储注册成功的服务对象和其服务方法的所有信息
        std::unordered_map<std::string, ServiceInfo> m_serviceMap;
    
    • 1
    • 2

    NotifyService的实现:

    // 这里是框架提供给外部使用的,可以发布rpc方法的函数接口
    void RpcProvider::NotifyService(google::protobuf::Service* service)
    {
        ServiceInfo service_info;
    
        // 获取了服务对象的描述信息
        const google::protobuf::ServiceDescriptor* pserviceDesc = service->GetDescriptor();
        // 获取服务的名字
        std::string service_name = pserviceDesc->name();
    
        // 获取服务对象service的方法的数量
        int methodCnt = pserviceDesc->method_count();
    
        std::cout << "service_name: " << service_name << std::endl;
    
        for (int i = 0; i < methodCnt; ++i)
        {
            // 获取了服务对象指定下标的服务方法的描述(抽象描述)
            const google::protobuf::MethodDescriptor* pmethodDesc = pserviceDesc->method(i);
            std::string method_name = pmethodDesc->name();
            service_info.m_methodMap.insert({method_name, pmethodDesc});
    
            std::cout << "method_name: " << method_name << std::endl;
        }
        service_info.m_service = service;
    
        m_serviceMap.insert({service_name, service_info});
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
  • 相关阅读:
    NNDL 实验三 线性回归
    【python】HTTP压力测试过程中遇到的问题与解决方案
    扬帆际海—shopee跨境店和本土店谁更有优势?
    微软Azure配置中心 App Configuration (二):Feature Flag 功能开关特性
    【HMS Core】【FAQ】运动健康、音频编辑、华为帐号服务 典型问题合集7
    Kotlin(八) 数据类、单例
    Kotlin(十四)泛型
    函数空间的数学理论指导深度学习模型的设计和训练
    Dubbo 原理与部署
    SaaSBase:什么是Oracle Fusion ERP?
  • 原文地址:https://blog.csdn.net/m0_56257585/article/details/126701860