《开源精选》是我们分享Github、Gitee等开源社区中优质项目的栏目,包括技术、学习、实用与各种有趣的内容。本期推荐的是一个Go语言RPC服务治理框架——RPCX。
介绍
RPCX是当前最流行的Go生态圈的微服务框架之一,很多大厂和创业公司都在使用,并且服务端无需额外配置,RPCX也同时支持HTTP调用,这样其它编程语言都可以调用RPCX服务, 是目前性能最好的 RPC 框架之一。
功能特性
-
• 简单易用:易于入门, 易于开发, 易于集成, 易于发布, 易于监控
-
• 高性能:性能远远高于 Dubbo、Motan、Thrift等框架,是gRPC性能的两倍
-
• 交叉平台,交叉语言:可以容易部署在Windows/Linux/MacOS等平台,支持各种编程语言的调用
-
• 服务发现:除了直连外,还支持 Zookeeper、Etcd、 Consul、mDNS等注册中心
-
• 服务治理:支持 Failover、 Failfast、 Failtry、Backup等失败模式,支持 随机、 轮询、权重、网络质量, 一致性哈希,地理位置等路由算法
快速起步
安装
安装 rpcx:
go get -u -v github.com/smallnest/rpcx/...
这一步只会安装 rpcx 的基础功能。如果想要使用 etcd 作为注册中心,需要加上 etcd 这个标签。
go get -u -v -tags "etcd" github.com/smallnest/rpcx/...
如果想要使用 quic ,也需要加上 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
定义Service
定义一个 Sevice 就像写一个单纯的 Go 结构体:
import "context"
type Args struct {
A int
B int
}
type Reply struct {
C int
}
type Arith int
func (t *Arith) Mul(ctx context.Context, args *Args, reply *Reply) error {
reply.C = args.A * args.B
return nil
}
-
• Arith 是一个 Go 类型,并且它有一个方法 Mul。方法 Mul 的 第 1 个参数是 context.Context。
-
• 方法 Mul 的 第 2 个参数是 args, args 包含了请求的数据 A 和 B。
-
• 方法 Mul 的 第 3 个参数是 reply, reply 是一个指向了 Reply 结构体的指针。
-
• 方法 Mul 的 返回类型是 error (可以为 nil)。方法 Mul 把 A * B 的结果 赋值到 Reply.C
以上已经定义了一个叫做 Arith 的 service, 并且为它实现了 Mul 方法。下一步骤中将会继续介绍如何把这个服务注册给服务器,并且如何用 client 调用它。
实现Server
三行代码就可以注册一个服务:
s := server.NewServer()
s.RegisterName("Arith", new(Arith), "")
s.Serve("tcp", ":8972")
这里把服务命名 Arith,你可以按照如下的代码注册服务。
s.Register(new(example.Arith), "")
实现Client
// #1
d := client.NewPeer2PeerDiscovery("tcp@"+*addr, "")
// #2
xclient := client.NewXClient("Arith", client.Failtry, client.RandomSelect, d, client.DefaultOption)
defer xclient.Close()
// #3
args := &example.Args{
A: 10,
B: 20,
}
// #4
reply := &example.Reply{}
// #5
err := xclient.Call(context.Background(), "Mul", args, reply)
if err != nil {
log.Fatalf("failed to call: %v", err)
}
log.Printf("%d * %d = %d", args.A, args.B, reply.C)
-
• #1 定义了使用什么方式来实现服务发现。在这里我们使用最简单的 Peer2PeerDiscovery(点对点)。客户端直连服务器来获取服务地址。
-
• #2 创建了 XClient, 并且传进去了 FailMode、 SelectMode 和默认选项。FailMode 告诉客户端如何处理调用失败:重试、快速返回,或者尝试另一台服务器。SelectMode 告诉客户端如何在有多台服务器提供了同一服务的情况下选择服务器。
-
• #3 定义了请求:这里我们想获得 10 * 20 的结果。当然我们可以自己算出结果是 200,但是我们仍然想确认这与服务器的返回结果是否一致。
-
• #4 定义了响应对象, 默认值是0值, 事实上 rpcx 会通过它来知晓返回结果的类型,然后把结果反序列化到这个对象。
-
• #5 调用了远程服务并且同步获取结果。
-
异步调用 Service
以下的代码可以异步调用服务:
d := client.NewPeer2PeerDiscovery("tcp@"+*addr2, "")
xclient := client.NewXClient("Arith", client.Failtry, client.RandomSelect, d, client.DefaultOption)
defer xclient.Close()
args := &example.Args{
A: 10,
B: 20,
}
reply := &example.Reply{}
call, err := xclient.Go(context.Background(), "Mul", args, reply, nil)
if err != nil {
log.Fatalf("failed to call: %v", err)
}
replyCall := <-call.Done
if replyCall.Error != nil {
log.Fatalf("failed to call: %v", replyCall.Error)
} else {
log.Printf("%d * %d = %d", args.A, args.B, reply.C)
}
性能测试
测试环境
-
• CPU : Intel(R) Xeon(R) CPU E5-2630 v3 @ 2.40GHz, 32 cores
-
• 内存:32G
-
• Go版本:1.9.0
-
• 操作系统:CentOS 7 / 3.10.0-229.el7.x86_64
采用
-
• protobuf
-
• 客户端和服务器在同一台服务器上
-
• 581 字节有效载荷
-
• 500/2000/5000 个并发客户端
-
• 模拟处理时间:0ms、10ms和30ms
测试结果
模拟 0ms 处理时间:
模拟 10ms 处理时间:
-
• 吞吐量
模拟 30ms 处理时间:
传送门
开源协议:Apache 2.0
开源地址:https://github.com/smallnest/rpcx
-END-
原文始发于微信公众号(开源技术专栏):Go语言开源RPC服务治理框架,很多大厂和创业公司都在使用
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/120599.html