主题
miniRPC —— 从零到一实现一个 Go RPC 框架
项目目标
使用 Go 语言从零实现一个名为 miniRPC 的轻量级 RPC 框架,以渐进式、模块化的方式逐章构建,最终形成一个具备生产参考价值的完整框架。
总体要求
- Go 版本:1.21+,使用 Go Modules 管理依赖
- 项目根目录:
/data/workspace/learnNote/miniRPC - 每个章节对应一个独立可运行的子目录(如
day1-codec/、day2-server/),同时在项目根目录维护一个持续演进的minirpc/核心库 - 代码风格遵循 Go 官方规范,通过
go vet和golint检查 - 每章需包含:可运行的示例代码(
example/)、单元测试(覆盖率 ≥ 80%)、README.md说明文档
章节规划
Day 1 — 消息编解码(Codec)
目标: 设计 RPC 消息协议格式,实现序列化/反序列化层
- 定义消息结构:Header(MagicNumber、ServiceMethod、Seq、Error)+ Body
- 实现
Codec接口,提供GobCodec和JsonCodec两种实现 - 支持通过
Option在连接握手阶段协商编解码方式 - 交付物: codec 包、编解码 benchmark 测试、协议格式说明文档
Day 2 — 服务端基础架构(Server)
目标: 实现高并发 TCP 服务端,能接收并处理 RPC 请求
- 基于
net.Listener实现连接监听与接入 - 实现请求的读取(readRequest)、处理(handleRequest)、响应(sendResponse)完整生命周期
- 使用
sync.Mutex保证响应的有序发送;使用sync.WaitGroup实现优雅等待 - 支持单连接上的并发请求处理
- 交付物: server 包、集成测试(模拟多并发请求)
Day 3 — 客户端与调用封装(Client)
目标: 实现支持异步和同步调用的 RPC 客户端
- 设计
Call结构体,封装一次 RPC 调用的完整生命周期(ServiceMethod、Args、Reply、Error、Done channel) - 实现
Client.Go()(异步)和Client.Call()(同步)两种调用方式 - 客户端并发安全:使用 pending map 管理进行中的请求,支持多 goroutine 共享同一连接
- 连接异常处理:服务端断开时,自动终止所有 pending 请求
- 交付物: client 包、异步/同步调用示例、错误场景测试
Day 4 — 服务注册与反射调用(Service)
目标: 实现服务的自动注册和基于反射的方法调用
- 定义 RPC 方法签名规范:
func (t *T) MethodName(args ArgType, reply *ReplyType) error - 使用
reflect包实现服务方法的自动发现与注册 - 参数/返回值类型校验,自动创建入参和出参实例
- 将 service 层集成到 Server 中,实现
ServiceMethod格式:Service.Method - 交付物: service 包、反射调用的 benchmark、端到端调用示例
Day 5 — HTTP 支持与调试页面
目标: 支持通过 HTTP 协议承载 RPC 调用,并提供 Web 调试界面
- 实现 HTTP CONNECT 方法进行协议切换(Hijack),复用已有 TCP 处理逻辑
- 客户端支持通过 HTTP 拨号连接 RPC 服务
- 提供
/debug/rpc页面,展示已注册服务及调用统计信息 - 交付物: HTTP 传输层代码、调试页面模板、HTTP 连接测试
Day 6 — 负载均衡与服务发现(Discovery)
目标: 实现客户端侧的服务发现与负载均衡机制
- 定义
Discovery接口,实现MultiServerDiscovery(手动多节点列表) - 实现
XClient封装,支持多节点调用 - 负载均衡策略:Random(随机)、RoundRobin(轮询),可扩展
- 提供
Broadcast模式:向所有节点广播请求,任一出错即返回错误,全部成功才成功 - 交付物: discovery + xclient 包、多节点调用示例、负载均衡策略测试
Day 7 — 超时与容错机制(Timeout)
目标: 在框架各关键环节引入超时控制,提升健壮性
- 连接超时:客户端拨号超时控制(
net.DialTimeout) - 调用超时:
Client.Call支持context.Context传入,通过select+time.After实现 - 服务端处理超时:
handleRequest增加超时控制,防止慢请求阻塞 - 优雅关闭:服务端支持信号监听,等待已有请求处理完毕后关闭
- 交付物: 超时控制集成代码、超时场景测试用例(连接超时/处理超时/调用超时)
Day 8 — 中间件与拦截器(Middleware)(可选进阶)
目标: 提供请求处理管线,支持日志、鉴权、限流等横切关注点
- 定义
Interceptor接口(Unary 拦截器) - 支持服务端和客户端分别注册拦截器链
- 内置实现:AccessLog 日志拦截器、Recovery panic 恢复拦截器
- 交付物: middleware 包、拦截器链测试、自定义拦截器示例
每章交付规范
dayN-xxx/
├── README.md # 本章学习目标、核心概念、架构图、关键代码讲解
├── doc/
│ └── design.md # 技术设计文档:接口定义、流程图、设计决策与取舍
├── example/
│ ├── server/
│ │ └── main.go # 可独立运行的服务端示例
│ └── client/
│ └── main.go # 可独立运行的客户端示例
├── <package>/
│ ├── *.go # 核心实现代码
│ └── *_test.go # 单元测试(覆盖率 ≥ 80%)
└── go.mod文档要求
- README.md: 用通俗的语言解释本章实现了什么、为什么这样设计、如何运行示例
- design.md: 包含接口设计(Go interface 定义)、核心流程时序图(可用 Mermaid)、与上一章的差异说明、关键设计决策的 trade-off 分析
- 所有文档使用中文编写
约束与风格
- 不使用任何第三方 RPC 框架(如 gRPC、rpcx),可使用标准库和基础工具库
- 优先可读性,代码中对关键设计决策添加注释说明(不要冗余注释)
- 每章代码可独立编译运行,不强依赖后续章节
- 变量/函数命名遵循 Go 惯例,包名简短有意义