一、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)
#ifndef MPRPCAPPLICATION_H
#define MPRPCAPPLICATION_H
#include <iostream>
#include <string>
#include <unordered_map>
#include <mutex>
// RPC框架核心应用类(单例模式)
class MprpcApplication {
public:
// 1. 单例获取:懒汉模式(线程安全)
static MprpcApplication& GetInstance();
// 2. 框架初始化:解析命令行参数 + 加载配置文件
// 命令行参数格式:./rpcserver -i config.conf
void Init(int argc, char** argv);
// 3. 通用配置获取接口
std::string GetConfig(const std::string& key);
// 4. 便捷配置获取接口(封装GetConfig,避免重复解析字符串)
std::string GetRpcServerIp(); // 获取RPC服务器IP
uint16_t GetRpcServerPort(); // 获取RPC服务器端口
std::string GetZkServerIp(); // 获取Zookeeper注册中心IP
uint16_t GetZkServerPort(); // 获取Zookeeper注册中心端口
// 5. 框架销毁:释放全局资源
void Destroy();
// 禁止拷贝和移动(单例模式必须)
MprpcApplication(const MprpcApplication&) = delete;
MprpcApplication& operator=(const MprpcApplication&) = delete;
MprpcApplication(MprpcApplication&&) = delete;
MprpcApplication& operator=(MprpcApplication&&) = delete;
private:
// 私有构造/析构:单例模式
MprpcApplication() = default;
~MprpcApplication() = default;
// 解析配置文件(内部辅助函数)
void LoadConfigFile(const std::string& config_file);
// 全局配置存储(key-value)
std::unordered_map<std::string, std::string> m_config_map;
// 单例锁(保证线程安全)
static std::mutex m_mutex;
static MprpcApplication* m_instance;
};
#endif // MPRPCAPPLICATION_H
2. 实现文件(mprpcapplication.cpp)
#include "mprpcapplication.h"
#include <unistd.h>
#include <string.h>
#include <sstream>
// 静态成员初始化
MprpcApplication* MprpcApplication::m_instance = nullptr;
std::mutex MprpcApplication::m_mutex;
// 1. 获取单例实例(线程安全的懒汉模式)
MprpcApplication& MprpcApplication::GetInstance() {
if (m_instance == nullptr) {
std::lock_guard<std::mutex> lock(m_mutex);
if (m_instance == nullptr) {
m_instance = new MprpcApplication();
}
}
return *m_instance;
}
// 2. 框架初始化核心逻辑
void MprpcApplication::Init(int argc, char** argv) {
if (argc < 2) {
std::cerr << "usage: " << argv[0] << " -i <config_file>" << std::endl;
exit(EXIT_FAILURE);
}
// 解析命令行参数(-i 指定配置文件)
int opt = 0;
std::string config_file;
while ((opt = getopt(argc, argv, "i:")) != -1) {
switch (opt) {
case 'i':
config_file = optarg;
break;
case '?':
std::cerr << "invalid option: " << static_cast<char>(optopt) << std::endl;
exit(EXIT_FAILURE);
case ':':
std::cerr << "option " << static_cast<char>(optopt) << " requires an argument" << std::endl;
exit(EXIT_FAILURE);
default:
break;
}
}
// 加载配置文件
LoadConfigFile(config_file);
// 初始化日志/网络等组件(可扩展)
std::cout << "MprpcApplication init success!" << std::endl;
std::cout << "rpcserver_ip: " << GetRpcServerIp() << std::endl;
std::cout << "rpcserver_port: " << GetRpcServerPort() << std::endl;
std::cout << "zookeeper_ip: " << GetZkServerIp() << std::endl;
std::cout << "zookeeper_port: " << GetZkServerPort() << std::endl;
}
// 解析配置文件(格式:key=value,忽略注释行#)
void MprpcApplication::LoadConfigFile(const std::string& config_file) {
FILE* fp = fopen(config_file.c_str(), "r");
if (fp == nullptr) {
std::cerr << "config file " << config_file << " not exist!" << std::endl;
exit(EXIT_FAILURE);
}
// 逐行解析配置
char buf[512] = {0};
while (fgets(buf, sizeof(buf), fp) != nullptr) {
// 去掉换行符/空格
std::string line(buf);
Trim(line);
// 跳过空行/注释行
if (line.empty() || line[0] == '#') {
continue;
}
// 解析key=value
size_t pos = line.find('=');
if (pos == std::string::npos) {
// 配置格式错误
continue;
}
std::string key = line.substr(0, pos);
std::string value = line.substr(pos + 1);
Trim(key);
Trim(value);
m_config_map[key] = value;
}
fclose(fp);
}
// 辅助函数:去除字符串首尾空格(内部使用)
void Trim(std::string& s) {
size_t start = s.find_first_not_of(" \t\r\n");
if (start == std::string::npos) {
s = "";
return;
}
size_t end = s.find_last_not_of(" \t\r\n");
s = s.substr(start, end - start + 1);
}
// 3. 通用配置获取
std::string MprpcApplication::GetConfig(const std::string& key) {
auto it = m_config_map.find(key);
if (it == m_config_map.end()) {
return "";
}
return it->second;
}
// 4. 便捷配置获取(封装类型转换)
std::string MprpcApplication::GetRpcServerIp() {
return GetConfig("rpcserver_ip");
}
uint16_t MprpcApplication::GetRpcServerPort() {
std::string port_str = GetConfig("rpcserver_port");
return std::stoi(port_str);
}
std::string MprpcApplication::GetZkServerIp() {
return GetConfig("zookeeper_ip");
}
uint16_t MprpcApplication::GetZkServerPort() {
std::string port_str = GetConfig("zookeeper_port");
return std::stoi(port_str);
}
// 5. 框架销毁(释放资源)
void MprpcApplication::Destroy() {
// 释放日志资源、网络连接、zk客户端句柄等(可扩展)
std::cout << "MprpcApplication destroy success!" << std::endl;
if (m_instance != nullptr) {
delete m_instance;
m_instance = nullptr;
}
}
3. 配置文件示例(config.conf)
# RPC框架配置文件
# 服务器配置
rpcserver_ip=127.0.0.1
rpcserver_port=8080
# Zookeeper注册中心配置
zookeeper_ip=127.0.0.1
zookeeper_port=2181
# 日志配置(可扩展)
log_path=./log
log_level=info
4. 测试使用示例(main.cpp)
#include "mprpcapplication.h"
int main(int argc, char** argv) {
// 1. 初始化RPC框架(核心步骤)
MprpcApplication::GetInstance().Init(argc, argv);
// 2. 获取配置参数
std::string rpc_ip = MprpcApplication::GetInstance().GetRpcServerIp();
uint16_t rpc_port = MprpcApplication::GetInstance().GetRpcServerPort();
std::cout << "=== 业务层获取配置 ===" << std::endl;
std::cout << "RPC Server IP: " << rpc_ip << std::endl;
std::cout << "RPC Server Port: " << rpc_port << std::endl;
// 3. 运行RPC服务器/客户端逻辑(可扩展)
// ...
// 4. 销毁框架(程序退出前)
MprpcApplication::GetInstance().Destroy();
return 0;
}
四、核心设计要点解析
-
单例模式:
- 采用懒汉模式 + 双检锁,保证线程安全且延迟初始化;
- 禁用拷贝 / 移动构造,避免多实例创建。
-
配置解析:
- 支持命令行参数
-i指定配置文件,符合 Linux 程序习惯; - 解析
key=value格式,忽略注释行和空行,兼容常见配置文件格式。
- 支持命令行参数
-
扩展性设计:
- 通用
GetConfig接口兼容新增配置项; - 便捷接口(如
GetRpcServerPort)封装类型转换,降低业务层使用成本; Destroy函数预留资源释放接口,可扩展日志、网络、注册中心等资源释放。
- 通用
-
错误处理:
- 初始化失败时直接退出并打印错误信息,避免框架带病运行;
- 配置文件不存在 / 格式错误时友好提示。
五、扩展方向(工业级优化)
- 配置热更新 :添加
ReloadConfig接口,支持不重启程序更新配置; - 配置校验 :初始化时校验必填配置(如
rpcserver_port必须是合法端口); - 日志集成:整合你之前的日志系统,将框架日志写入指定路径;
- 注册中心初始化 :在
Init中初始化 Zookeeper 客户端,封装到MprpcApplication; - 饿汉模式:若框架启动时必须初始化,可改为饿汉单例(提前创建实例)。
总结
MprpcApplication是 RPC 框架的入口类,核心是单例管理 + 配置加载 + 全局参数访问;- 核心接口
Init负责框架初始化,GetConfig/ 便捷接口负责参数获取,Destroy负责资源释放; - 设计要点:线程安全的单例、灵活的配置解析、低耦合的扩展接口。
关键点回顾
- 单例模式:懒汉 + 双检锁,保证全局唯一且线程安全;
- 初始化流程:解析命令行参数 → 加载配置文件 → 初始化核心组件;
- 配置访问:通用接口兼容扩展,便捷接口降低使用成本。