Go 語言開源 RPC 服務治理框架
介紹
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 處理時間:
-
• 吞吐量
-
-
• 平均延遲
-
-
• P99 延遲
-
模擬 10ms 處理時間:
- • 吞吐量
-
• 平均延遲
-
-
• P99 延遲
-
模擬 30ms 處理時間:
-
• 吞吐量
-
-
• 平均延遲
-
-
• P99 延遲
-
傳送門
開源協議:Apache 2.0
開源地址:https://github.com/smallnest/rpcx
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/7xZszeKi5fNC-Ndcm51sjA