RPCX 分布式的RPC

最后更新于:2022-04-02 02:49:48

[TOC] > [作者文章](https://colobu.com/2016/05/26/RPCX-a-distributed-rpc-dubbo-like-framework-by-Go/#RPC%E6%98%AF%E4%BB%80%E4%B9%88) > [github](http://github.com/smallnest/rpcx) > ## 概述 原因在于尽管这些框架(grpc ,net/rpc 等)都是为Go实现的RPC库,但是它们的功能比较单一,只是实现了点对点(End-to-End)的通讯框架。缺乏服务治理的功能,比如服务注册和发现、 负载均衡、容灾、服务监控等功能。因此我基于Go net/rpc框架实现了一个类似Dubbo的分布式框架。 * 基于net/rpc,可以将net/rpc实现的RPC项目轻松的转换为分布式的RPC * 插件式设计,可以配置所需的插件,比如服务发现、日志、统计分析等 * 基于TCP长连接,只需很小的额外的消息头 * 支持多种编解码协议,如Gob、Json、MessagePack、gencode、ProtoBuf等 * 服务发现:服务发布、订阅、通知等,支持多种发现方式如ZooKeeper、Etcd等 * 高可用策略:失败重试(Failover)、快速失败(Failfast) * 负载均衡:支持随机请求、轮询、低并发优先、一致性 Hash等 * 规模可扩展,可以根据性能的需求增减服务器 * 其他:调用统计、访问日志等 ### 服务发现 * [Peer to Peer](https://books.studygolang.com/go-rpc-programming-guide/part2/registry.html#peer2peer): 客户端直连每个服务节点。 the client connects the single service directly. It acts like the`client`type. * [Peer to Multiple](https://books.studygolang.com/go-rpc-programming-guide/part2/registry.html#multiple): 客户端可以连接多个服务。服务可以被编程式配置。 * [Zookeeper](https://books.studygolang.com/go-rpc-programming-guide/part2/registry.html#zookeeper): 通过 zookeeper 寻找服务。 * [Etcd](https://books.studygolang.com/go-rpc-programming-guide/part2/registry.html#etcd): 通过 etcd 寻找服务。 * [Consul](https://books.studygolang.com/go-rpc-programming-guide/part2/registry.html#consul): 通过 consul 寻找服务。 * [mDNS](https://books.studygolang.com/go-rpc-programming-guide/part2/registry.html#mdns): 通过 mDNS 寻找服务(支持本地服务发现)。 * [In process](https://books.studygolang.com/go-rpc-programming-guide/part2/registry.html#inprocess): 在同一进程寻找服务。客户端通过进程调用服务,不走TCP或UDP,方便调试使用。 ## 客户端特性 ### 故障模式: * [Failfast](https://books.studygolang.com/go-rpc-programming-guide/part3/failmode.html#failfast):如果调用失败,立即返回错误 * [Failover](https://books.studygolang.com/go-rpc-programming-guide/part3/failmode.html#failover):选择其他节点,直到达到最大重试次数 * [Failtry](https://books.studygolang.com/go-rpc-programming-guide/part3/failmode.html#failtry):选择相同节点并重试,直到达到最大重试次数 ### 负载均衡选择器: * [Random](https://books.studygolang.com/go-rpc-programming-guide/part3/selector.html#random_selector): 随机选择节点 * [Roundrobin](https://books.studygolang.com/go-rpc-programming-guide/part3/selector.html#roundrobin_selector): 使用[roundrobin](https://zh.wikipedia.org/wiki/%E5%BE%AA%E7%92%B0%E5%88%B6)算法选择节点 * [Consistent hashing](https://books.studygolang.com/go-rpc-programming-guide/part3/selector.html#hash_selector): 如果服务路径、方法和参数一致,就选择同一个节点。使用了非常快的[jump consistent hash](https://arxiv.org/abs/1406.2294)算法。 * [Weighted](https://books.studygolang.com/go-rpc-programming-guide/part3/selector.html#weighted_selector): 根据元数据里配置好的权重(`weight=xxx`)来选择节点。类似于nginx里的实现(smooth weighted algorithm) * [Network quality](https://books.studygolang.com/go-rpc-programming-guide/part3/selector.html#ping_selector): 根据`ping`的结果来选择节点。网络质量越好,该节点被选择的几率越大。 * [Geography](https://books.studygolang.com/go-rpc-programming-guide/part3/selector.html#geo_selector): 如果有多个数据中心,客户端趋向于连接同一个数据机房的节点。 * [Customized Selector](https://books.studygolang.com/go-rpc-programming-guide/part3/selector.html#user_selector): 如果以上的选择器都不适合你,你可以自己定制选择器。例如一个rpcx用户写过它自己的选择器,他有2个数据中心,但是这些数据中心彼此有限制,不能使用`Network quality`来检测连接质量。 ### 广播与群发 `Broadcast`表示向所有服务器发送请求,只有**所有**服务器正确返回时才会成功。此时FailMode 和 SelectMode的设置是无效的。请设置超时来避免阻塞。 `Fork`表示向所有服务器发送请求,只要**任意一**台服务器正确返回就成功。此时FailMode 和 SelectMode的设置是无效的。 ``` xClient := client.NewXClient(router, conf.GetRpcFailMode(), conf.GetRpcSelectMode(), d, client.DefaultOption) xClient.Fork() xClient.Broadcast() ``` ### 扩展点 可对一下扩展点进行扩展,Client的扩展点如下: 读取Response Header的前后 读取Response Body的前后 写Request的前后 ## Benchmark pcx基于Go net/rpc框架实现,它的插件机制并不会带来多少性能的损失 ``` [root@localhost rpcx]# go test -bench . -test.benchmem PASS BenchmarkNetRPC_gob-16 100000 18742 ns/op 321 B/op 9 allocs/op BenchmarkNetRPC_jsonrpc-16 100000 21360 ns/op 1170 B/op 31 allocs/op BenchmarkNetRPC_msgp-16 100000 18617 ns/op 776 B/op 35 allocs/op BenchmarkRPCX_gob-16 100000 18718 ns/op 320 B/op 9 allocs/op BenchmarkRPCX_json-16 100000 21238 ns/op 1170 B/op 31 allocs/op BenchmarkRPCX_msgp-16 100000 18635 ns/op 776 B/op 35 allocs/op BenchmarkRPCX_gencodec-16 100000 18454 ns/op 4485 B/op 17 allocs/op BenchmarkRPCX_protobuf-16 100000 17234 ns/op 733 B/op 13 allocs/op ``` ## 安装 安装 rpcx: `go get -u -v github.com/smallnest/rpcx/... ` 如果你想要使用 etcd 作为注册中心,加上etcd这个标签。 `go get -u -v -tags "etcd" github.com/smallnest/rpcx/... ` 如果你想要使用 quic `go get -u -v -tags "quic etcd" github.com/smallnest/rpcx/... ` 方便起见,我推荐你安装所有的tags,即使你现在并不需要他们: `go get -u -v -tags "reuseport quic kcp zookeeper etcd consul ping" github.com/smallnest/rpcx/... ` tags 对应: * quic: 支持 quic 协议 * kcp: 支持 kcp 协议 * zookeeper: 支持 zookeeper 注册中心 * etcd: 支持 etcd 注册中心 * consul: 支持 consul 注册中心 * ping: 支持 网络质量负载均衡 * reuseport: 支持 reuseport ## 问题 ### undefined: resolver.BuildOption undefined: resolver.ResolveNowOption [参考](http://54wcs.com/post/%E5%A4%84%E7%90%86go1.13%E4%B8%8Betcd.v3%E9%94%99%E8%AF%AF%E9%97%AE%E9%A2%98/) 1. 修改 go.mod ``` replace github.com/coreos/go-systemd => github.com/coreos/go-systemd/v22 v22.0.0 replace google.golang.org/grpc => google.golang.org/grpc v1.26.0 ``` `go get ./...`
';