一、MprpcApplication 核心职责
MprpcApplication是 RPC 框架的 “管家”,核心作用:
- 单例模式:全局唯一实例,避免重复初始化;
- 配置加载:解析 RPC 框架的配置文件(如服务器 IP、端口、日志路径、注册中心地址等);
- 框架初始化:启动时初始化日志、网络、注册中心等核心组件;
- 全局参数访问:提供接口获取配置参数(如获取服务器端口、注册中心地址);
- 框架销毁:程序退出时释放资源。
二、MprpcApplication 核心接口设计
以下是工业级 RPC 框架中MprpcApplication的标准接口设计(按功能分类):
| 接口类型 | 接口名 | 功能描述 |
|---|---|---|
| 单例获取 | GetInstance() | 获取全局唯一的MprpcApplication实例(懒汉 / 饿汉单例) |
| 初始化 | Init(int argc, char** argv) | 解析命令行参数 + 加载配置文件,初始化框架(核心入口) |
| 配置获取 | GetConfig(const std::string& key) | 根据 key 获取配置值(如 "rpcserver_ip") |
| 便捷配置获取 | GetRpcServerIp() | 快捷获取 RPC 服务器 IP(封装GetConfig) |
| 便捷配置获取 | GetRpcServerPort() | 快捷获取 RPC 服务器端口 |
| 便捷配置获取 | GetZkServerIp() | 快捷获取 Zookeeper 注册中心 IP |
| 框架销毁 | Destroy() | 释放框架资源(日志、网络连接、注册中心句柄等) |
三、MprpcApplication 完整实现代码
以下是可直接编译运行的MprpcApplication实现,包含单例、配置加载、参数访问等核心功能:
1. 头文件(mprpcapplication.h)
1#ifndef MPRPCAPPLICATION_H 2#define MPRPCAPPLICATION_H 3 4#include <iostream> 5#include <string> 6#include <unordered_map> 7#include <mutex> 8 9// RPC框架核心应用类(单例模式) 10class MprpcApplication { 11public: 12 // 1. 单例获取:懒汉模式(线程安全) 13 static MprpcApplication& GetInstance(); 14 15 // 2. 框架初始化:解析命令行参数 + 加载配置文件 16 // 命令行参数格式:./rpcserver -i config.conf 17 void Init(int argc, char** argv); 18 19 // 3. 通用配置获取接口 20 std::string GetConfig(const std::string& key); 21 22 // 4. 便捷配置获取接口(封装GetConfig,避免重复解析字符串) 23 std::string GetRpcServerIp(); // 获取RPC服务器IP 24 uint16_t GetRpcServerPort(); // 获取RPC服务器端口 25 std::string GetZkServerIp(); // 获取Zookeeper注册中心IP 26 uint16_t GetZkServerPort(); // 获取Zookeeper注册中心端口 27 28 // 5. 框架销毁:释放全局资源 29 void Destroy(); 30 31 // 禁止拷贝和移动(单例模式必须) 32 MprpcApplication(const MprpcApplication&) = delete; 33 MprpcApplication& operator=(const MprpcApplication&) = delete; 34 MprpcApplication(MprpcApplication&&) = delete; 35 MprpcApplication& operator=(MprpcApplication&&) = delete; 36 37private: 38 // 私有构造/析构:单例模式 39 MprpcApplication() = default; 40 ~MprpcApplication() = default; 41 42 // 解析配置文件(内部辅助函数) 43 void LoadConfigFile(const std::string& config_file); 44 45 // 全局配置存储(key-value) 46 std::unordered_map<std::string, std::string> m_config_map; 47 48 // 单例锁(保证线程安全) 49 static std::mutex m_mutex; 50 static MprpcApplication* m_instance; 51}; 52 53#endif // MPRPCAPPLICATION_H 54
2. 实现文件(mprpcapplication.cpp)
1#include "mprpcapplication.h" 2#include <unistd.h> 3#include <string.h> 4#include <sstream> 5 6// 静态成员初始化 7MprpcApplication* MprpcApplication::m_instance = nullptr; 8std::mutex MprpcApplication::m_mutex; 9 10// 1. 获取单例实例(线程安全的懒汉模式) 11MprpcApplication& MprpcApplication::GetInstance() { 12 if (m_instance == nullptr) { 13 std::lock_guard<std::mutex> lock(m_mutex); 14 if (m_instance == nullptr) { 15 m_instance = new MprpcApplication(); 16 } 17 } 18 return *m_instance; 19} 20 21// 2. 框架初始化核心逻辑 22void MprpcApplication::Init(int argc, char** argv) { 23 if (argc < 2) { 24 std::cerr << "usage: " << argv[0] << " -i <config_file>" << std::endl; 25 exit(EXIT_FAILURE); 26 } 27 28 // 解析命令行参数(-i 指定配置文件) 29 int opt = 0; 30 std::string config_file; 31 while ((opt = getopt(argc, argv, "i:")) != -1) { 32 switch (opt) { 33 case 'i': 34 config_file = optarg; 35 break; 36 case '?': 37 std::cerr << "invalid option: " << static_cast<char>(optopt) << std::endl; 38 exit(EXIT_FAILURE); 39 case ':': 40 std::cerr << "option " << static_cast<char>(optopt) << " requires an argument" << std::endl; 41 exit(EXIT_FAILURE); 42 default: 43 break; 44 } 45 } 46 47 // 加载配置文件 48 LoadConfigFile(config_file); 49 50 // 初始化日志/网络等组件(可扩展) 51 std::cout << "MprpcApplication init success!" << std::endl; 52 std::cout << "rpcserver_ip: " << GetRpcServerIp() << std::endl; 53 std::cout << "rpcserver_port: " << GetRpcServerPort() << std::endl; 54 std::cout << "zookeeper_ip: " << GetZkServerIp() << std::endl; 55 std::cout << "zookeeper_port: " << GetZkServerPort() << std::endl; 56} 57 58// 解析配置文件(格式:key=value,忽略注释行#) 59void MprpcApplication::LoadConfigFile(const std::string& config_file) { 60 FILE* fp = fopen(config_file.c_str(), "r"); 61 if (fp == nullptr) { 62 std::cerr << "config file " << config_file << " not exist!" << std::endl; 63 exit(EXIT_FAILURE); 64 } 65 66 // 逐行解析配置 67 char buf[512] = {0}; 68 while (fgets(buf, sizeof(buf), fp) != nullptr) { 69 // 去掉换行符/空格 70 std::string line(buf); 71 Trim(line); 72 73 // 跳过空行/注释行 74 if (line.empty() || line[0] == '#') { 75 continue; 76 } 77 78 // 解析key=value 79 size_t pos = line.find('='); 80 if (pos == std::string::npos) { 81 // 配置格式错误 82 continue; 83 } 84 85 std::string key = line.substr(0, pos); 86 std::string value = line.substr(pos + 1); 87 Trim(key); 88 Trim(value); 89 m_config_map[key] = value; 90 } 91 92 fclose(fp); 93} 94 95// 辅助函数:去除字符串首尾空格(内部使用) 96void Trim(std::string& s) { 97 size_t start = s.find_first_not_of(" \t\r\n"); 98 if (start == std::string::npos) { 99 s = ""; 100 return; 101 } 102 size_t end = s.find_last_not_of(" \t\r\n"); 103 s = s.substr(start, end - start + 1); 104} 105 106// 3. 通用配置获取 107std::string MprpcApplication::GetConfig(const std::string& key) { 108 auto it = m_config_map.find(key); 109 if (it == m_config_map.end()) { 110 return ""; 111 } 112 return it->second; 113} 114 115// 4. 便捷配置获取(封装类型转换) 116std::string MprpcApplication::GetRpcServerIp() { 117 return GetConfig("rpcserver_ip"); 118} 119 120uint16_t MprpcApplication::GetRpcServerPort() { 121 std::string port_str = GetConfig("rpcserver_port"); 122 return std::stoi(port_str); 123} 124 125std::string MprpcApplication::GetZkServerIp() { 126 return GetConfig("zookeeper_ip"); 127} 128 129uint16_t MprpcApplication::GetZkServerPort() { 130 std::string port_str = GetConfig("zookeeper_port"); 131 return std::stoi(port_str); 132} 133 134// 5. 框架销毁(释放资源) 135void MprpcApplication::Destroy() { 136 // 释放日志资源、网络连接、zk客户端句柄等(可扩展) 137 std::cout << "MprpcApplication destroy success!" << std::endl; 138 if (m_instance != nullptr) { 139 delete m_instance; 140 m_instance = nullptr; 141 } 142} 143
3. 配置文件示例(config.conf)
1# RPC框架配置文件 2# 服务器配置 3rpcserver_ip=127.0.0.1 4rpcserver_port=8080 5 6# Zookeeper注册中心配置 7zookeeper_ip=127.0.0.1 8zookeeper_port=2181 9 10# 日志配置(可扩展) 11log_path=./log 12log_level=info 13
4. 测试使用示例(main.cpp)
1#include "mprpcapplication.h" 2 3int main(int argc, char** argv) { 4 // 1. 初始化RPC框架(核心步骤) 5 MprpcApplication::GetInstance().Init(argc, argv); 6 7 // 2. 获取配置参数 8 std::string rpc_ip = MprpcApplication::GetInstance().GetRpcServerIp(); 9 uint16_t rpc_port = MprpcApplication::GetInstance().GetRpcServerPort(); 10 std::cout << "=== 业务层获取配置 ===" << std::endl; 11 std::cout << "RPC Server IP: " << rpc_ip << std::endl; 12 std::cout << "RPC Server Port: " << rpc_port << std::endl; 13 14 // 3. 运行RPC服务器/客户端逻辑(可扩展) 15 // ... 16 17 // 4. 销毁框架(程序退出前) 18 MprpcApplication::GetInstance().Destroy(); 19 20 return 0; 21} 22
四、核心设计要点解析
- 单例模式:
- 采用懒汉模式 + 双检锁,保证线程安全且延迟初始化;
- 禁用拷贝 / 移动构造,避免多实例创建。
- 配置解析:
- 支持命令行参数
-i指定配置文件,符合 Linux 程序习惯; - 解析
key=value格式,忽略注释行和空行,兼容常见配置文件格式。
- 支持命令行参数
- 扩展性设计:
- 通用
GetConfig接口兼容新增配置项; - 便捷接口(如
GetRpcServerPort)封装类型转换,降低业务层使用成本; Destroy函数预留资源释放接口,可扩展日志、网络、注册中心等资源释放。
- 通用
- 错误处理:
- 初始化失败时直接退出并打印错误信息,避免框架带病运行;
- 配置文件不存在 / 格式错误时友好提示。
五、扩展方向(工业级优化)
- 配置热更新:添加
ReloadConfig接口,支持不重启程序更新配置; - 配置校验:初始化时校验必填配置(如
rpcserver_port必须是合法端口); - 日志集成:整合你之前的日志系统,将框架日志写入指定路径;
- 注册中心初始化:在
Init中初始化 Zookeeper 客户端,封装到MprpcApplication; - 饿汉模式:若框架启动时必须初始化,可改为饿汉单例(提前创建实例)。
总结
MprpcApplication是 RPC 框架的入口类,核心是单例管理 + 配置加载 + 全局参数访问;- 核心接口
Init负责框架初始化,GetConfig/ 便捷接口负责参数获取,Destroy负责资源释放; - 设计要点:线程安全的单例、灵活的配置解析、低耦合的扩展接口。
关键点回顾
- 单例模式:懒汉 + 双检锁,保证全局唯一且线程安全;
- 初始化流程:解析命令行参数 → 加载配置文件 → 初始化核心组件;
- 配置访问:通用接口兼容扩展,便捷接口降低使用成本。
《RPC分布式通信(3)--RPC基础框架接口》 是转载文章,点击查看原文。

