Best microservices framework in Go, like alibaba Dubbo, but with more features, Scale easily. Try it. Test it. If you feel it's better, use it! 𝐉𝐚𝐯𝐚有𝐝𝐮𝐛𝐛𝐨, 𝐆𝐨𝐥𝐚𝐧𝐠有𝐫𝐩𝐜𝐱! build for cloud!

RAW Doc

Refactor Simplify Design

代码简化设计文档 (Refactor & Simplify)

本文档记录对最近一轮重构(god-object 文件拆分 + 插件错误日志 + 方法白名单注册)
简化 review 与落地改动。目标是质量,不涉及正确性 bug 修复。

1. 背景

最近的提交(HEAD~11...HEAD)主要做了两件事:

1. 文件拆分:把两个"上帝对象"拆成职责内聚的小文件。
- client/xclient.go (1212 行) → xclient_broadcast.go / xclient_call.go
/ xclient_discovery.go / xclient_transfer.go
- server/server.go (799 行) → server_conn.go / server_dispatch.go
/ server_response.go / server_shutdown.go
2. 行为增强:把之前 _ = plugin.DoXxx(...) 吞掉的错误改为记录日志;新增
RegisterWithMethods 方法白名单注册;空白名单守卫。

拆分本身是逐行搬移(byte-for-byte),四位 reviewer 一致确认搬移无漂移。
真正需要简化的是新增逻辑

2. 发现与处理

四个维度(Reuse / Simplification / Efficiency / Altitude)并行 review,去重后
落地如下改动。

2.1 已修复

| # | 文件 | 问题 | 简化后 |
|---|------|------|--------|
| 1 | server/service.go | 三重空白名单守卫RegisterWithMethodsRegisterNameWithMethods 各有一次 len(methods)==0 检查,register() 内部 else 分支又重复了第三次(且错误文案不同)。第三处对白名单路径不可达(两个公开入口已拦截)。 | 删除 register() 内的死分支,改为注释说明:空 slice 会自然落到下方"no suitable methods"检查。规则收敛,文案不再三份。 |
| 2 | server/service.go | RegisterWithMethods 缺少 nil-Plugins 守卫RegisterName/RegisterNameWithMethodsDoRegister 前都有 if s.Plugins == nil 兜底,唯独 RegisterWithMethods 没有,与同族方法不一致(潜在 nil 解引用)。 | 补齐 if s.Plugins == nil { s.Plugins = &pluginContainer{} },与同族方法对齐。 |
| 3 | server/server_shutdown.go | 拆分留下的接缝垃圾Serve 的文档注释被搬到 shutdown 文件却无对应函数(悬空注释);getDoneChan 被搬来后全仓零调用(死代码)。 | 删除死函数 getDoneChan 与悬空注释;把 Serve 的文档注释还给 server.goServe 函数上方。 |
| 4 | server/service.go | reflect.PtrTo 已废弃(编译器 diagnostic)。 | 替换为 reflect.PointerTo。 |
| 5 | server/plugin_test.go | 新增的 waitServerReady(返回 bool,goroutine 安全)已用于消除 goroutine 内的 t.Fatalf,但 TestPluginHeartbeat 的子 goroutine 里还残留一处 t.Fatalfgo vet 报警)。 | 改为 t.Errorf + return,补全该模式,go vet 干净。 |

2.2 已评估但跳过(避免改变意图或超出 diff 范围)

- 插件错误日志"每调用点手写"而非收敛到 pluginContainer(Altitude 提出):
reviewer 建议把"吞错并记日志 vs 返回错误"的策略下沉到 container 内部,让调用点
统一 _ = 或统一返回。这是合理的深层改进,但涉及重新设计 Do* 方法族的
错误契约,波及所有插件调用点,远超本次 review 的 diff 范围,且属于行为/接口
变更(/simplify 明确排除)。留作后续独立重构项。当前每处日志的 message 各有
上下文(servicePath.method),并非可折叠的 copy-paste。

- 方法白名单未复用/泛化 suitableMethods(Altitude/Reuse 提出):白名单路径
自己重走 allpicked,并额外 MethodByName 探测以区分"不存在"与"签名不合适"。
reviewer 建议给 suitableMethods 加过滤器参数统一两条路径。这会改动核心注册机制
的签名与语义,属于设计层变更,跳过——现有实现正确且已复用 suitableMethods
的产出,MethodByName 探测仅用于生成更友好的错误文案,代价可接受。

- nil vs len==0 语义registermethods == nil 表示"注册全部",非 nil
表示白名单。这是刻意的哨兵语义,公开 API 已在边界拦住空 slice,改为显式 intent
参数属于 API 变更,跳过

- doc-only / 注释冗长share/context.goclient/discovery.go):均为文档
措辞层面,不影响逻辑,跳过

- xclient_discovery.go watch() 去掉了 sort.Slice:这是减少工作量而非
回归,且属搬移期的既有行为变更(前序提交 cd34c37 已单独处理),不在本次范围

3. 拆分边界评估(Altitude)

四位 reviewer 一致认为新文件边界内聚合理

- Server 侧:conn(监听/连接/单请求读取/鉴权)、dispatch(请求分发/函数调用/错误)、
response(发送响应)、shutdown(生命周期/优雅关闭/重启)——四个真实职责簇。
- Client 侧:broadcast(Broadcast/Fork/Inform 扇出)、call(Call/Go/SendRaw/wrap)、
discovery(watch/选点/缓存客户端)、transfer(SendFile/DownloadFile/Stream)。

无 awkward 的跨文件依赖,无"拆错位置"的接缝(除已修的 #3)。

4. 验证

text
go build ./...              # 通过
go vet ./server ./client ./share # 干净(原 t.Fatalf 报警已消除)
go test ./server -count=1 # ok (11.7s)

5. 结论

拆分本身干净,无需改动。新增逻辑修掉了 5 处质量问题(死代码、不一致守卫、接缝
垃圾、废弃 API、测试 vet 报警),核心收益是空白名单规则从三处收敛到边界一处
同族注册方法的 nil-Plugins 守卫对齐。两项更深的设计改进(插件错误策略下沉、
白名单泛化 suitableMethods)超出 /simplify 范围,记录留待后续。

---

CHANGELOG

rpcx

1.9.4


- switch the experimental rdma transport from rsocket to gordma's rdmanet.Conn (build tag rdma)
- add RegisterWithMethods/RegisterNameWithMethods to register only a whitelist of a struct's methods (#581)
- document server plugin extension points (execution order, parameters, return values) in godoc (#645)
- fix printf argument mismatches surfaced by go vet


1.9.0


- unregister all services on close automatically
- add PostHTTPRequestPlugin
- support io_uring
- add CacheDiscovery
- add Oneshot method for XClient
- support RDMA


1.8.0


- supports distributed rate limiter based on go-redis/redis-rate
- move zookeeper plugin to https://github.com/smallnest/rpcx-zookeepr
- move consul plugin to https://github.com/smallnest/rpcx-consul
- move redis plugin to https://github.com/smallnest/rpcx-redis
- move influxd/opentelemetry plugin to https://github.com/smallnest/rpcx-plugins
- you can write customized error, for example {"code": 500, err: "internal error"}
- server support the work pool by WithPool
- support to write services like go std http router style without reflect
- simplify async write for service
- improve performance


1.7.0


- move etcd support to github.com/rpcxio/rpcx-etcd
- Broken API: NewXXXDiscovery returns error instead of panic
- support AdvertiseAddr in FileTransfer
- support Auth for OneClientPool
- support Auth for XClientPool
- Broken API: add meta parameter for SendFile/DownloadFile
- support streaming between server side and client side
- support DNS as service discovery
- support rpcx flow tracing
- support websocket as the transport like tcp,kcp and quic
- add CMuxPlugin to allow developing customzied services by using the same single port
- re-tag rpcx to make sure the version is less than 2 (for go module)
- support visit grpc services by rpcx clients: https://github.com/rpcxio/rpcxplus/tree/master/grpcx
- support configing grpc servicves in rpcx server side
- improve rpcx performance
- add Inform method in XClient
- add memory connection for unit tests
- supports opentelemetry

1.6.0

- support reflection
- add kubernetes config example
- improve nacos support
- improve message.Encode performance
- re-register services in etcd v3
- avoid duplicated client creation
- add SelectNodePlugin that can interrupt the Select method
- support TcpCopy by TeePlugin
- support reuseport for http invoke
- return reply even in case of server errors
- Change two methods' name of client plugin!
- Broken API: add error parameter in PreWriteResponse(#486)
- Broken API: change ReadTimeout/WriteTimeout to IdleTimeout
- Support passing Deadline of client contexts to server side
- remove InprocessClient plugin
- use heartbeat/tcp_keepalive to avoid client hanging


1.5.0

- support jsonrpc 2.0
- support CORS for jsonrpc 2.0
- support opentracing and opencensus
- upload/download files by streaming
- add Pool for XClient and OneClient
- remove rudp support
- add ConnCreated plugin. Yu can use it to set KCP UDPSession
- update client plugins. All plugin returns error instead of bool
- support ETCD 3.0 API
- support redis as registry
- support redis DB selection
- fix RegisterFunction issues
- add Filter for clients
- remove most of build tags such as etcd, zookeeper,consul,reuseport
- add Nacos as registry http://nacos.io
- support blacklist and whitlist

1.4.0

- Support utp and rudp
- Add OneClient to support invoke multile servicesby one client
- Finish compress feature
- Add more plugins for monitoring connection
- Support dynamic port allocation
- Use go module to manage dependencies
- Support shutdown graceful
- Add rpcx-java to support develop raw java services and clients
- Support thrift codec
- Setup rpcx offcial site: http://rpcx.io
- Add Chinese document: http://cn.doc.rpcx.io or https://smallnest.gitbooks.io/go-rpc-programming-guide

1.3.1

- Add http gateway: https://github.com/rpcxio/rpcx-gateway
- Add direct http invoke
- Add bidirectional communication
- Add xgen tool to generate codes for services automatically


fix bugs.

1.3.0

- Rewrite rpcx. It implements its protocol and won't implemented based on wrapper of go standard rpc lib
- Add go tags for pluggable plugins
- Add English document: https://github.com/smallnest/rpcx-programming
- Add rpcx 3.0 examples: https://github.com/rpcxio/rpcx-examples

rpcx 3.0 is not compatible with rpcx 2.0 and below

---

README

- stable branch: v1.7.x
- development branch: master

<a href="https://rpcx.io/"><img height="160" src="http://rpcx.io/logos/rpcx-logo-text.png"></a>

Official site: http://rpcx.io

[](https://opensource.org/licenses/Apache-2.0) [](http://godoc.org/github.com/smallnest/rpcx) [](https://github.com/smallnest/rpcx/actions) [](https://goreportcard.com/report/github.com/smallnest/rpcx) [](https://coveralls.io/github/smallnest/rpcx?branch=master) [](_documents/rpcx_dev_qq3.jpg)

Notice: etcd

since rpcx 1.7.6, some plugins have been moved to the independent project:

- etcd plugin has been moved to rpcx-etcd
- zookeeper plugin has been moved to rpcx-zookeeper
- consul plugin has been moved to rpcx-consul
- redis plugin has been moved to rpcx-redis
- influxdb plugin has been moved to rpcx-plugins
- opentelemetry plugin has been moved to rpcx-plugins

Announce

Stable branch: v1.9.4

A tcpdump-like tool added: rpcxdump。 You can use it to debug communications between rpcx services and clients.


Cross-Languages


you can use other programming languages besides Go to access rpcx services.

- rpcx-gateway: You can write clients in any programming languages to call rpcx services via rpcx-gateway
- http invoke: you can use the same http requests to access rpcx gateway
- Java Services/Clients: You can use rpcx-java to implement/access rpcx services via raw protocol.
- rust rpcx: You can write rpcx services in rust by rpcx-rs

If you can write Go methods, you can also write rpc services. It is so easy to write rpc applications with rpcx.

Installation

install the basic features:

go get -v github.com/smallnest/rpcx/...


If you want to use quickcp registry, use those tags to go getgo build or go run. For example, if you want to use all features, you can:

sh
go get -v -tags "quic kcp" github.com/smallnest/rpcx/...

_tags_:
- quic: support quic transport
- kcp: support kcp transport
- rdma: support the experimental RDMA transport (built on gordma's rdmanet.Conn; requires libibverbs on Linux)

Which companies are using rpcx?

<p float="left">
<img style="padding-bottom: 20px;" src="https://user-images.githubusercontent.com/865763/102993220-b967f000-4557-11eb-9747-703a6cbb9fb1.png" width="200" />
<img style="padding-bottom: 20px;" src="https://user-images.githubusercontent.com/865763/113414067-a8e4d280-93ee-11eb-9f42-1373d7e766c1.png" width="200" />
<img style="padding-bottom: 20px;" src="https://user-images.githubusercontent.com/865763/102993433-267b8580-4558-11eb-9e45-4e1a86d61688.png" width="200" />
<img style="padding-bottom: 20px;" src="https://user-images.githubusercontent.com/865763/102993530-4743db00-4558-11eb-9f76-1ee69e992b82.png" width="200" />
<img style="padding-bottom: 20px;" src="https://user-images.githubusercontent.com/865763/102993612-722e2f00-4558-11eb-849a-3264c430aef9.png" width="200" />
<img style="padding-bottom: 20px;" src="https://user-images.githubusercontent.com/865763/102993785-c20cf600-4558-11eb-82b9-27b801aca4ff.png" width="200" />
</p>

Features


rpcx is a RPC framework like Alibaba Dubbo and Weibo Motan.

rpcx is created for targets:
1. Simple: easy to learn, easy to develop, easy to integrate and easy to deploy
2. Performance: high performance (>= grpc-go)
3. Cross-platform: support _raw slice of bytes_, _JSON_, _Protobuf_ and _MessagePack_. Theoretically it can be used with java, php, python, c/c++, node.js, c# and other platforms
4. Service discovery and service governance: support zookeeper, etcd and consul.


It contains below features
- Support raw Go functions. There's no need to define proto files.
- Pluggable. Features can be extended such as service discovery, tracing.
- Support TCP, HTTP, QUIC and KCP
- Support multiple codecs such as JSON, Protobuf, MessagePack and raw bytes.
- Service discovery. Support peer2peer, configured peers, zookeeper, etcd, consul and mDNS.
- Fault tolerance:Failover, Failfast, Failtry.
- Load banlancing:support Random, RoundRobin, Consistent hashing, Weighted, network quality and Geography.
- Support Compression.
- Support passing metadata.
- Support Authorization.
- Support heartbeat and one-way request.
- Other features: metrics, log, timeout, alias, circuit breaker.
- Support bidirectional communication.
- Support access via HTTP so you can write clients in any programming languages.
- Support API gateway.
- Support backup request, forking and broadcast.


rpcx uses a binary protocol and platform-independent, which means you can develop services in other languages such as Java, python, nodejs, and you can use other prorgramming languages to invoke services developed in Go.

There is a UI manager: rpcx-ui.

Performance

Test results show rpcx has better performance than other rpc framework except standard rpc lib.


The benchmark code is at rpcx-benchmark.

Listen to others, but test by yourself.

_Test Environment_

- CPU: Intel(R) Xeon(R) CPU E5-2630 v3 @ 2.40GHz, 32 cores
- Memory: 32G
- Go: 1.9.0
- OS: CentOS 7 / 3.10.0-229.el7.x86_64

_Use_
- protobuf
- the client and the server on the same server
- 581 bytes payload
- 500/2000/5000 concurrent clients
- mock processing time: 0ms, 10ms and 30ms

_Test Result_

mock 0ms process time

<table><tr><th>Throughputs</th><th>Mean Latency</th><th>P99 Latency</th></tr><tr><td width="30%"><img src="http://colobu.com/2018/01/31/benchmark-2018-spring-of-popular-rpc-frameworks/p0-throughput.png"></td><td width="30%"><img src="http://colobu.com/2018/01/31/benchmark-2018-spring-of-popular-rpc-frameworks/p0-latency.png"></td><td width="30%"><img src="http://colobu.com/2018/01/31/benchmark-2018-spring-of-popular-rpc-frameworks/p0-p99.png"></td></tr></table>


mock 10ms process time

<table><tr><th>Throughputs</th><th>Mean Latency</th><th>P99 Latency</th></tr><tr><td width="30%"><img src="http://colobu.com/2018/01/31/benchmark-2018-spring-of-popular-rpc-frameworks/p10-throughput.png"></td><td width="30%"><img src="http://colobu.com/2018/01/31/benchmark-2018-spring-of-popular-rpc-frameworks/p10-latency.png"></td><td width="30%"><img src="http://colobu.com/2018/01/31/benchmark-2018-spring-of-popular-rpc-frameworks/p10-p99.png"></td></tr></table>


mock 30ms process time

<table><tr><th>Throughputs</th><th>Mean Latency</th><th>P99 Latency</th></tr><tr><td width="30%"><img src="http://colobu.com/2018/01/31/benchmark-2018-spring-of-popular-rpc-frameworks/p30-throughput.png"></td><td width="30%"><img src="http://colobu.com/2018/01/31/benchmark-2018-spring-of-popular-rpc-frameworks/p30-latency.png"></td><td width="30%"><img src="http://colobu.com/2018/01/31/benchmark-2018-spring-of-popular-rpc-frameworks/p30-p99.png"></td></tr></table>


Examples

You can find all examples at rpcxio/rpcx-examples.

The below is a simple example.


Server

go
// define example.Arith
……

s := server.NewServer()
s.RegisterName("Arith", new(example.Arith), "")
s.Serve("tcp", addr)

#### Registering only selected methods

Register/RegisterName expose every suitable exported method of a struct as
RPC. To expose only some of them, use RegisterWithMethods /
RegisterNameWithMethods with a whitelist of method names:

go
// Arith has exported methods Mul, Add and Sub, but only Mul/Add
// should be callable remotely.
s := server.NewServer()
err := s.RegisterWithMethods(new(example.Arith), []string{"Mul", "Add"}, "")
// err := s.RegisterNameWithMethods("Arith", new(example.Arith), []string{"Mul", "Add"}, "")
s.Serve("tcp", addr)

Rules of the whitelist:

- Whitelist only: methods not listed are not registered, so a newly added
method stays private unless you opt it in.
- Errors on bad names: a name that does not exist on the receiver, or that
exists but is not a suitable RPC method, makes registration fail (the two
cases give different error messages). Nothing is partially registered.
- Empty whitelist errors: pass a non-empty list, or use Register /
RegisterName to register all methods.

Client

go
// prepare requests
……

d, err := client.NewPeer2PeerDiscovery("tcp@"+addr, "")
xclient := client.NewXClient("Arith", client.Failtry, client.RandomSelect, d, client.DefaultOption)
defer xclient.Close()
err = xclient.Call(context.Background(), "Mul", args, reply, nil)

Contributors

<a href="https://github.com/smallnest/rpcx/graphs/contributors">
<img src="https://contrib.rocks/image?repo=smallnest/rpcx" />
</a>


Contribute

see contributors.

Welcome to contribute:
- submit issues or requirements
- send PRs
- write projects to use rpcx
- write tutorials or articles to introduce rpcx

License

Apache License, Version 2.0

---