# mprpc **Repository Path**: stone_scx/mprpc ## Basic Information - **Project Name**: mprpc - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-08-21 - **Last Updated**: 2025-08-22 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # mpRPC框架 [toc] ## RPC通信 RPC的全称是 **Remote Procedure Call**,即**远程过程调用**。它允许你像调用本地函数一样去调用一个位于另一台计算机(远程服务器)上的函数或方法。其核心目标是让分布式系统中的网络通信对开发者透明化。你不需要直接处理复杂的网络编程细节(如Socket连接、数据打包解包、网络传输、异常处理等),只需要关注业务逻辑本身。 一个成熟的RPC框架通常包含以下组件: - **序列化/反序列化**:将代码的数据结构与二进制字节流相互转换。要求**高效**(速度快、体积小)和**跨语言**。 - **网络传输层**:负责可靠的数据传输。C++框架通常基于高性能I/O模型. - **服务治理**: - **服务发现**:集成ZooKeeper, Etcd, Nacos, Consul等服务注册中心。 - **负载均衡**:提供多种策略(如轮询、随机、加权、一致性哈希)。 - **熔断降级**:防止故障服务拖垮整个系统。 - **链路追踪**:集成OpenTelemetry, Zipkin等,用于诊断问题。 ## 网络通信 项目使用muduo网络库作为底层通信。核心特点与设计理念如下: 1. **非阻塞IO + IO多路复用**:核心基于 `epoll`(Linux)和 `poll`,实现了高并发连接处理,非常适合开发长连接服务,如即时通讯、游戏服务器、RPC框架等。 2. **One loop per thread + thread pool**: - **One loop per thread**:每个线程运行一个EventLoop(事件循环),处理IO事件。这是一种常见的多Reactor模型,主Acceptor接收新连接,然后将连接分发给多个Sub Reactor处理IO,有效分散压力。 - **Thread pool**:用于处理计算密集型任务,防止阻塞IO线程。 3. **基于事件回调**:用户注册回调函数来处理连接建立、消息到达、连接关闭等事件。这种异步风格需要遵循特定的编程模式。 4. **原生支持多核**:通过合理的线程模型,可以轻松利用多核CPU的性能。 5. **只支持Linux**:紧密依赖于Linux的先进特性,如`timerfd`, `eventfd`等,以实现更统一、高效的事件驱动。 6. **现代C++风格**:大量使用`std::function`, `std::bind`, `shared_ptr`等,资源管理清晰,避免了原生指针的混乱。 ### 安装 ~~~bash # muduo依赖与boost sudo apt install gcc g++ sudo apt install mpi-default-dev libicu-dev libbz2-dev # 下载并解压boost源码 # https://www.boost.org/releases/latest/ cd boost # 配置 ./bootstrap.sh --prefix=/usr/local # 编译并安装(共享库和静态库) sudo ./b2 link=shared,static -j$(nproc) install # 如果安装到系统默认目录后仍提示boost库未找到,则需要手动安装到/usr/lib/x86_64-linux-gnu/目录下: sudo chmod -x stage/lib/libboost*.so.* sudo cp stage/lib/libboost*.so.* /usr/lib/x86_64-linux-gnu/ # 卸载方法 sudo rm -rf /usr/local/include/boost sudo rm -rf /usr/local/lib/libboost* # 检查 Boost 版本 cat /usr/local/include/boost/version.hpp | grep "BOOST_VERSION" # 检查库文件 ls /usr/local/lib/libboost_* | head -10 # 特别检查 system 和 filesystem 库 ls /usr/local/lib/libboost_system* 2>/dev/null || echo "Boost System library not found" ls /usr/local/lib/libboost_filesystem* 2>/dev/null || echo "Boost Filesystem library not found" # 编译安装muduo网络库 # 源码目录里面的CMakeLists.txt文件第13行控制测试用例代码,注释后取消编译 ./build.sh ./build.sh install # 此时muduo的头文件和lib库文件放到了muduo-master同级目录下的build目录下的release-install-cpp11文件夹下面了 cd release-install-cpp11/include/ mv muduo/ /usr/include/ cd ../lib/ mv * /usr/local/lib/ ~~~ `````c++ // 验证boost的安装 g++ -std=c++11 test_boost_linked.cpp -o test_boost_linked -lboost_filesystem -lboost_system #include #include // 获取Boost版本号 #include // 使用一个简单的算法头文件 #include // 使用一个简单的容器头文件 int main() { // 1. 打印Boost版本号 std::cout << "Boost version: " << BOOST_VERSION / 100000 << "." // 主版本号 << BOOST_VERSION / 100 % 1000 << "." // 次版本号 << BOOST_VERSION % 100 // 补丁号 << std::endl; // 2. 测试一个仅头文件的库功能 (Boost.Algorithm) std::string test_str = "hello world"; boost::to_upper(test_str); std::cout << "Uppercase string: " << test_str << std::endl; // 3. 测试另一个仅头文件的库功能 (Boost.Array) boost::array arr = {1, 2, 3}; std::cout << "Array element: " << arr[0] << std::endl; std::cout << "Boost header-only libraries test passed successfully!" << std::endl; return 0; } ````` ~~~c++ // 验证muduo的安装 g++ -std=c++11 simplest_muduo_test.cpp -o simplest_test -lmuduo_net -lmuduo_base -lpthread #include #include #include using namespace muduo; using namespace muduo::net; int main() { std::cout << "Testing Muduo basic functionality..." << std::endl; try { // 测试1: 创建事件循环(muduo核心组件) EventLoop loop; std::cout << "✓ EventLoop created successfully" << std::endl; // 测试2: 创建地址对象 InetAddress addr(8888); std::cout << "✓ InetAddress created successfully" << std::endl; // 测试3: 创建TCP服务器 TcpServer server(&loop, addr, "TestServer"); std::cout << "✓ TcpServer created successfully" << std::endl; // 测试4: 设置简单的回调函数 server.setConnectionCallback([](const TcpConnectionPtr& conn) { if (conn->connected()) { std::cout << "✓ Connection callback works" << std::endl; } }); std::cout << "✓ All basic Muduo components initialized successfully!" << std::endl; std::cout << "Muduo library is properly installed!" << std::endl; } catch (const std::exception& e) { std::cerr << "Error: " << e.what() << std::endl; return 1; } return 0; } ~~~ ## 数据序列化与反序列化 项目使用Protocol Buffers(简称protobuf)是Google开发的一种**语言中立、平台中立、可扩展**的**序列化结构化数据**的机制。它类似于XML或JSON,但更小、更快、更简单。 #### 核心特点与工作流程 1. **定义数据结构**:你需要在一个 `.proto` 文件中定义你想要序列化的数据的**结构**。 ```protobuf // person.proto message Person { required string name = 1; required int32 id = 2; optional string email = 3; } ``` 2. **编译生成代码**:使用Protocol Buffers编译器 `protoc` 编译这个 `.proto` 文件。它会生成对应语言(如C++, Java, Python)的代码。 - 生成 `person.pb.cc` 和 `person.pb.h`(C++) - 这些生成的类提供了高效的API来操作(设置、读取)定义的消息,以及将它们序列化成二进制格式或从二进制格式反序列化。 3. **高效序列化**: - **二进制格式**:序列化后的数据是二进制流,体积非常小。 - **高效的编码方式**:如Varints编码,对小的整数值用更少的字节表示。 - **速度快**:序列化/反序列化的速度通常远快于XML和JSON。 ## 分布服务管理 Apache ZooKeeper 是一个**分布式的、开放源码的分布式应用程序协调服务**。它提供了一个类似于文件系统的**树形命名空间**(znodes),以及一套丰富的**原语**,用于构建分布式系统的基础设施。 ### 核心概念与功能 1. **ZNode**:ZooKeeper数据模型中的节点,类似于文件系统中的文件和目录。它可以存储少量数据(字节数组),并且分为**持久节点**和**临时节点**。 - **临时节点**:**与客户端会话绑定**。当创建它的客户端会话失效时,该节点会被自动删除。这个特性是实现**服务发现**和**领导者选举**的关键。 2. **Watch机制**:客户端可以在ZNode上设置监听(Watch)。当该ZNode发生变化(数据变更、子节点增减)时,ZooKeeper会主动通知客户端。这是一种**发布-订阅**模型,避免了客户端轮询。 3. **保证一致性**:ZooKeeper集群自身是一个分布式系统,它为客户提供**顺序一致性**和**原子性**保证。 4. **集群高可用**:通常以集群模式部署(奇数个节点,如3、5、7台),只要超过半数的机器存活,服务就是可用的。 ### 解决了什么问题?(提供了什么分布式原语?) ZooKeeper本身不直接处理业务,而是为分布式系统提供“工具箱”,解决协调难题: - **服务发现**:服务提供者将自己的地址信息作为**临时节点**注册到ZooKeeper。服务消费者监听该父节点,从而动态感知所有可用服务的列表。 - **配置管理**:将全局配置存储在一个ZNode上,所有应用程序监听这个节点,一旦配置修改,所有应用都能收到通知并获取最新配置。 - **分布式锁**:通过创建**顺序临时节点**来实现高效的分布式互斥锁。 - **领导者选举**:多个服务实例同时竞争创建一个指定的ZNode,最终只有一个能创建成功,成为Leader,其他成为Follower。利用**临时节点**的特性,Leader宕机后会话结束,节点删除,其他Follower可以立即重新选举。 - **命名服务**:通过树形结构提供统一的资源命名。 - **集群管理**:通过监听节点的上下线,可以掌握集群中机器的状态。