- 集群和分布式概念与原理
- RPC 远程过程调用原理及其实现
- protobuf 序列化与反序列化
- ZooKeeper分布式一致性协调服务应用于编程
- muduo 网络库编程
- conf 配置文件读取
- 异步日志
- CMake 构建项目集成编译环境
集群: 每一台服务器独立运行一个工程的所有模块。
分布式: 一个工程拆分了很多模块,每一个模块独立部署运行在一个服务器主机上,所有服务器协同工 作共同提供服务,每一台服务器称作分布式的一个节点,根据节点的并发要求,对一个节点可以再做节点模块集群部署。
RPC(Remote Procedure Call Protocol)远程过程调用协议。
黄色部分: 设计 rpc 方法参数的打包和解析,也就是数据的序列化和反序列化,使用protobuf
绿色部分 :网络部分,包括寻找rpc服务主机,发起rpc调用请求和响应rpc调用结果,使用muduo网络库和zookeeper服务配置中心
bin: 可执行文件
build: 项目编译文件
lib: 项目库文件
src: 源文件
test: 测试代码
example: 框架代码使用范例
CMakeLists.txt: 顶层的cmake文件
README.md: 项目自述文件
autobuild.sh: 一键编译脚本
accept + read/write: 不是并发服务器
accept + fork - process-per-connection : 适合并发连接数不大,计算任务工作量大于 fork开销
accept + thread - thread-per-connection : 比方案2开销小一点,但是并发造成线程堆积过多
muduo的设计: reactors in threads - one loop per thread : 方案的特点是 one loop per thread, 有一个 main reactor(I/O)负载 accept 连接,然后把连接分发到某个 sub reactor(Woker), 该连接的所有操作那个 sub reactor 所在的线程中完成,多个连接可能被分配到多个线程中,充分利用CPU
reactors in process - one loop per process: Nginx网络器的网络模块设计,基于进程设计,采用多个Reactors充当 I/O 进程和工作进程,通过一把 accept锁,完美解决了多个 Reactors的"敬群现象"
Zookeeper 是一个分布式协调服务,由 Apache 开源,用于解决分布式系统中的一致性、配置管理、命名服务、分布式锁等问题。它的核心设计目标是:
- 高可用性(HA)
- 强一致性(CP 系统)
- 简单的树形数据模型(类似文件系统)
核心特性:
| 特性 | 说明 |
|---|---|
| 顺序一致性 | 所有请求按顺序执行 |
| 原子性 | 操作要么成功要么失败,无中间状态 |
| 单一视图 | 所有客户端看到的数据一致 |
| 高可用 | 集群中多数节点存活即可服务 |
| 实时性 | 客户端最终能看到最新数据 |
Zookeeper 采用树形命名空间(ZNode存储数据,类似文件系统:
/ (根节点)
├── /service
│ ├── /service/api (存储服务地址)
│ └── /service/db
└── /config
└── /config/database (存储数据库配置)
ZNode 类型:
| 类型 | 说明 |
|---|---|
| 持久节点(PERSISTENT) | 永久存在,需手动删除 |
| 临时节点(EPHEMERAL) | 客户端会话结束自动删除 |
| 顺序节点(SEQUENTIAL) | 节点名自动追加单调递增序号 |
// 加锁(创建临时顺序节点)
String lockPath = zk.create("/lock/seq-", EPHEMERAL_SEQUENTIAL);
List<String> children = zk.getChildren("/lock", false);
if (isLowestSeqNode(children, lockPath)) {
// 获取锁
} else {
// 监听前一个节点
}
// 解锁(删除节点)
zk.delete(lockPath);// 服务注册(临时节点)
zk.create("/services/service1", "192.168.1.1:8080".getBytes(), EPHEMERAL);
// 服务发现(监听节点变化)
List<String> services = zk.getChildren("/services", event -> {
System.out.println("服务列表变化: " + event.getPath());
});// 写入配置
zk.setData("/config/db_url", "jdbc:mysql://localhost:3306".getBytes(), -1);
// 监听配置变化
byte[] data = zk.getData("/config/db_url", event -> {
System.out.println("配置已更新");
}, null);| 命令 | 说明 |
|---|---|
create /path data |
创建节点 |
get /path |
获取节点数据 |
set /path newData |
更新节点 |
delete /path |
删除节点 |
ls /path |
列出子节点 |
stat /path |
查看节点状态 |

