gRPC负载均衡
gRPC负载均衡
负载均衡是gRPC的关键特性之一,它允许将来自客户端的请求分发到多个服务器上。这有助于防止任何一台服务器过载,并允许系统通过添加更多服务器进行扩展。
名称解析器为gRPC负载平衡策略提供服务器IP地址列表。策略负责维护到服务器的连接(子通道),并在发送RPC请求时选择要使用的连接。
配置方法
gRPC提供了一些负载均衡策略值得注意的是 “pick_first”(默认值),“round_robin” 和 “grpclb”。
在客户端调用 “grpc.Dial()” 方法来建立与服务端连接时,使用 “grpc.WithDefaultServiceConfig()” 传入配置选项,配置项使用 json 格式。
例如下面的代码,配置了 “round_robin” 负载均衡策略。
// 连接到服务端,配置 “round_robin” 负载均衡策略
conn, err := grpc.Dial(
"scheme:///serviceName",
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"LoadBalancingPolicy": "%s"}`, roundrobin.Name)),
)
示例
接口定义
// 指定 proto 的版本
syntax = "proto3";
// 指定生成的 go 文件存放位置及其包名
option go_package = ".;proto";
// 定义服务
service Hello {
rpc SayHello(Request) returns (Response);
}
// 定义消息体
message Request {
string requestName = 1;
}
message Response {
string responseMsg = 1;
}
服务端
package main
import (
pb "GoStudy/grpc/load_balance/proto"
"context"
"fmt"
"net"
"sync"
"google.golang.org/grpc"
)
var addrs = []string{"localhost:8811", "localhost:8812", "localhost:8813"}
type server struct {
pb.UnimplementedHelloServer
addr string
}
func (s *server) SayHello(ctx context.Context, req *pb.Request) (*pb.Response, error) {
return &pb.Response{ResponseMsg: "Hello " + req.GetRequestName() + " [FROM ]" + s.addr}, nil
}
func SatrtServer(addr string) {
// 开启监听端口
lis, _ := net.Listen("tcp", addr)
// 创建gRPC服务
grpcServer := grpc.NewServer()
// 在grpc服务端注册我们编写的服务
pb.RegisterHelloServer(grpcServer, &server{addr: addr})
// 启动服务
err := grpcServer.Serve(lis)
if err != nil {
fmt.Printf("grpcServer start failed: %v", err)
return
}
}
func main() {
var wg sync.WaitGroup
for _, addr := range addrs {
wg.Add(1)
go func(addr string) {
defer wg.Done()
SatrtServer(addr)
}(addr)
}
wg.Wait()
}
客户端
package main
import (
pb "GoStudy/grpc/load_balance/proto"
"context"
"fmt"
"google.golang.org/grpc"
"google.golang.org/grpc/balancer/roundrobin"
"google.golang.org/grpc/credentials/insecure"
)
const (
scheme = "example"
serviceName = "hello"
)
func main() {
// 连接到服务端,未使用安全连接
conn, err := grpc.Dial(
scheme+":///"+serviceName,
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"LoadBalancingPolicy": "%s"}`, roundrobin.Name)),
)
if err != nil {
fmt.Printf("connect to grpcServer failed: %v", err)
return
}
defer conn.Close()
// 创建 grpc 客户端
client := pb.NewHelloClient(conn)
// 执行 rpc 调用
for i := 0; i < 10; i++ {
resp1, _ := client.SayHello(context.Background(), &pb.Request{RequestName: "Macle"})
fmt.Println(resp1.GetResponseMsg())
}
}
名称解析器(Resolver)
因为 gRPC 默认使用 DNS 解析方案,在本地不方便进行测试使用,所以此处实现了一个简易的 Resolver。
package main
//实现自定义的名称解析器
import (
"google.golang.org/grpc/resolver"
)
var addrs = []string{"localhost:8811", "localhost:8812", "localhost:8813"}
func init() {
resolver.Register(&exampleResolverBuilder{})
}
type exampleResolver struct {
cc resolver.ClientConn
addrs []string
}
func (e *exampleResolver) ResolveNow(resolver.ResolveNowOptions) {}
func (e *exampleResolver) Close() {}
func (e *exampleResolver) updateState() {
var addrList resolver.State
for _, addr := range e.addrs {
addrList.Addresses = append(addrList.Addresses, resolver.Address{Addr: addr})
}
e.cc.UpdateState(addrList)
}
type exampleResolverBuilder struct{}
func (b *exampleResolverBuilder) Build(target resolver.Target, cc resolver.ClientConn, opts resolver.BuildOptions) (resolver.Resolver, error) {
er := &exampleResolver{
cc: cc,
addrs: addrs,
}
er.updateState()
return er, nil
}
func (b *exampleResolverBuilder) Scheme() string {
return scheme
}
目录结构如下
load_balance
│
├─client
│ main.go
│ resolver.go
│
├─proto
│ hello.pb.go
│ hello.proto
│ hello_grpc.pb.go
│
└─server
main.go
运行结果
启动服务后,再运行客户端。
可以看到客户端发起了十次RPC调用,结果基本符合轮询特征。
PS E:\GoStudy\grpc\load_balance\client> go run .\main.go .\resolver.go
Hello Macle [FROM ]localhost:8812
Hello Macle [FROM ]localhost:8813
Hello Macle [FROM ]localhost:8811
Hello Macle [FROM ]localhost:8812
Hello Macle [FROM ]localhost:8813
Hello Macle [FROM ]localhost:8811
Hello Macle [FROM ]localhost:8812
Hello Macle [FROM ]localhost:8813
Hello Macle [FROM ]localhost:8811
Hello Macle [FROM ]localhost:8812
PS E:\GoStudy\grpc\load_balance\client>

浙公网安备 33010602011771号