基于 TCP 自研的轻量级 RPC 框架,支持 JSON / Protobuf 编解码、gzip 压缩、自定义二进制协议(含粘包处理)、连接池 + Future 异步调用、etcd 服务注册发现、负载均衡(轮询 / 随机 / 平滑加权轮询)、熔断与令牌桶限流,附带两个压测工具。
go test -race -count=1 ./...测试覆盖编解码往返、gzip 压缩解压、协议帧切分(粘包/半包)、TCP 读写链路等核心场景,由 GitHub Actions 在每次提交时自动执行(gofmt / go vet / go test -race)。
- Go 1.25+
- etcd v3.5.x(当前项目已在 etcd v3.5.16 上验证通过)
- Windows / Linux / macOS 均可运行
-
从 GitHub Releases 下载
etcd-v3.5.16-windows-amd64.zip:Invoke-WebRequest -Uri "https://github.com/etcd-io/etcd/releases/download/v3.5.16/etcd-v3.5.16-windows-amd64.zip" -OutFile E:\etcd.zip Expand-Archive -Path E:\etcd.zip -DestinationPath E:\etcd -Force
-
启动 etcd 服务(默认监听
localhost:2379):E:\etcd\etcd-v3.5.16-windows-amd64\etcd.exe --data-dir E:\etcd\data
-
验证 etcd 是否正常:
$env:ETCDCTL_API = "3" E:\etcd\etcd-v3.5.16-windows-amd64\etcdctl.exe endpoint health # 期望输出:127.0.0.1:2379 is healthy E:\etcd\etcd-v3.5.16-windows-amd64\etcdctl.exe put hello world E:\etcd\etcd-v3.5.16-windows-amd64\etcdctl.exe get hello # 期望输出:hello / world
如果双击 etcd.exe 闪退,说明启动失败,常见原因是 2379 端口被占用,可通过
--listen-client-urls指定其他端口。
cd E:\CodeZone\go\LojiRPC
go build ./...也可以把各个入口编译成可执行文件,方便直接运行:
New-Item -ItemType Directory -Force -Path .\bin
go build -o .\bin\server1.exe ./cmd/server1
go build -o .\bin\server2.exe ./cmd/server2
go build -o .\bin\client.exe ./cmd/client
go build -o .\bin\bench1.exe ./cmd/bench1
go build -o .\bin\bench2.exe ./cmd/bench2两个服务端分别监听 :9090 和 :9091,启动后会自动注册到 etcd:
E:\CodeZone\go\LojiRPC\bin\server1.exe # 注册 Arith + Arith2 @ localhost:9090
E:\CodeZone\go\LojiRPC\bin\server2.exe # 注册 Arith @ localhost:9091验证服务端是否正常监听:
netstat -ano | Select-String ":9090|:9091"验证 etcd 注册信息(期望看到 3 个 key):
$env:ETCDCTL_API = "3"
E:\etcd\etcd-v3.5.16-windows-amd64\etcdctl.exe get --prefix /lojiRPC/services/
# /lojiRPC/services/Arith/localhost:9090 -> localhost:9090
# /lojiRPC/services/Arith/localhost:9091 -> localhost:9091
# /lojiRPC/services/Arith2/localhost:9090 -> localhost:9090客户端每 5 秒向 Arith.Add 发送 3 个异步请求,并通过 Future 等待结果:
E:\CodeZone\go\LojiRPC\bin\client.exe期望输出:
====== 新的一轮请求 ======
Add 0+0 result: 0
Add 1+1 result: 2
Add 2+2 result: 4
====== 新的一轮请求 ======
Add 3+3 result: 6
...
# -c 并发客户端数(默认 100)
# -n 请求总数(默认 10000)
# -b 每批异步请求数(默认 100)
E:\CodeZone\go\LojiRPC\bin\bench1.exe -c 100 -n 10000 -b 100输出 QPS、成功/失败数、平均延迟。
# -c 并发数(默认 50)
# -d 持续时间秒(默认 10)
E:\CodeZone\go\LojiRPC\bin\bench2.exe -c 20 -d 5参考结果(本机实测:20 并发跑 5 秒):
Total Requests: 34630
Success: 34630
Failed: 0
QPS: 6920.95
Avg Latency: 2.89 ms
P50 Latency: 2.71 ms
P90 Latency: 4.72 ms
P99 Latency: 5.89 ms
运行期间观察客户端日志中的 选择的地址为: localhost:9090 / localhost:9091 交替出现,说明轮询负载均衡生效。
Stop-Process -Name server1,server2,etcd -Force- etcd 启动闪退:通常是 2379 端口被占用,杀掉占用进程或改用
--listen-client-urls http://localhost:12379换端口。 - 服务端日志看不到输出:Go 的
log默认写到 stderr,后台启动时需重定向2>err.log;示例进程的日志分别写在bin\server1.err.log、bin\server2.err.log。 - 客户端报
registry not configured:说明Client创建时没有传入 etcd 注册中心,需要先启动 etcd 并确保localhost:2379可访问。 - 实例数量变化时
WeightedRR会返回空实例:平滑加权轮询目前要求实例数与构造时的权重数一致,动态扩缩容场景请使用默认的RoundRobin。