grpc外部負荷イコライザテスト
10917 ワード
grpc外部負荷イコライザテスト
(金慶のコラム2020.4)
grpcは、各リクエストに対して負荷等化を行う.負荷の均等化には、次の方法があります.
gRPCにおける負荷等化の主なメカニズムは外部負荷等化である.
gRPCは、外部負荷等化サービスのインタフェースを定義します.https://github.com/grpc/grpc/tree/master/src/proto/grpc/lb/v1
標準的なgrpclb実装は現在、https://github.com/joa/jawlb. JAwlbはKubernetes APIを介してサービスを発見する.
次のテストgrpcクライアントはjawlb服からサーバリストをクエリーし、サービスを要求します.まず、本機で複数のgreeter服のインスタンスを開き、ポートが異なります.その後greeterクライアントを変更し、greeter服アドレスに直接接続するのではなくjawlb服アドレスを割り当てます.同時にjawlbを変更し、サービス発見を削除し、固定出力ローカルサービスリストに変更し、タイミングを切り替えます.
greeterとはgrpc-goの例です:grpc-goexampleshelloworldgreeter
greeter服変更
パラメータを追加してサービスポートを指定します.
package main
import (
"fmt"
"log"
"net"
"github.com/spf13/pflag"
"github.com/spf13/viper"
"golang.org/x/net/context"
"google.golang.org/grpc"
pb "google.golang.org/grpc/examples/helloworld/helloworld"
)
// GreeterServer is used to implement helloworld.GreeterServer.
type GreeterServer struct {
}
// SayHello implements helloworld.GreeterServer
func (s *GreeterServer) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
msg := fmt.Sprintf("Hello %s from server-%d", in.Name, viper.GetInt("port"))
return &pb.HelloReply{Message: msg}, nil
}
func main() {
pflag.Int("port", 8000, "server bind port")
pflag.Parse()
viper.BindPFlags(pflag.CommandLine)
port := viper.GetInt("port")
addr := fmt.Sprintf(":%d", port)
lis, err := net.Listen("tcp", addr)
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
pb.RegisterGreeterServer(s, &GreeterServer{})
s.Serve(lis)
}
greeterクライアント変更
package main
import (
"context"
"log"
"os"
"time"
"github.com/sirupsen/logrus"
"google.golang.org/grpc"
_ "google.golang.org/grpc/balancer/grpclb"
pb "google.golang.org/grpc/examples/helloworld/helloworld"
"google.golang.org/grpc/grpclog"
"google.golang.org/grpc/resolver"
"google.golang.org/grpc/resolver/manual"
)
const (
defaultName = "world"
)
func init() {
grpclog.SetLogger(logrus.New())
}
func main() {
rb := manual.NewBuilderWithScheme("whatever")
rb.InitialState(resolver.State{Addresses: []resolver.Address{
{Addr: "127.0.0.1:8888", Type: resolver.GRPCLB},
}})
conn, err := grpc.Dial("whatever:///this-gets-overwritten", grpc.WithInsecure(), grpc.WithBlock(),
grpc.WithResolvers(rb))
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
c := pb.NewGreeterClient(conn)
name := defaultName
if len(os.Args) > 1 {
name = os.Args[1]
}
for {
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
r, err := c.SayHello(ctx, &pb.HelloRequest{Name: name})
cancel()
if err != nil {
log.Fatalf("could not greet: %v", err)
time.Sleep(time.Second)
continue
}
log.Printf("Greeting: %s", r.GetMessage())
time.Sleep(time.Second)
}
}
次の変更があります.
通常のgrpclbはDNSにSRVレコードを設定し、ここでDNSの設定を避けるテストを行い、カスタム解析器を採用し、コードに数行増えた.DNSで設定するメリットは、バックエンドIPとして直接解析したり、grpclbを追加したりすることで、コード上でバックエンドに直接接続するようにすることができます.
conn, err := grpc.Dial("dns:///myservice.domain.com", grpc.WithInsecure())
JAwlb変更
main.go
すべての構成を削除し、ホスト8888ポートのリスニングを固定するように変更します.
envconfig.MustProcess("JAWLB", &cfg)
func listen() (conn net.Listener, err error) {
conn, err = net.Listen("tcp", ":8888")
return
}
watch.go
package main
import (
"context"
"fmt"
"net"
"time"
)
func watchService(ctx context.Context) (_
すべてのサービス発見コードを削除し、10秒ごとにポートを切り替えるように変更します:80108020 8018021
うんてん
jawlb
λ jawlb.exe
2020/04/16 15:35:17 waiting for TERM
i = 1
2020/04/16 15:35:27 endpoints:
2020/04/16 15:35:27 127.0.0.1:8011
2020/04/16 15:35:27 127.0.0.1:8021
i = 2
2020/04/16 15:35:37 endpoints:
2020/04/16 15:35:37 127.0.0.1:8010
2020/04/16 15:35:37 127.0.0.1:8020
server
4つのインスタンスを実行します.
server --port 8010
server --port 8020
server --port 8011
server --port 8021
client
λ client
INFO[0002] lbBalancer: handle SubConn state change: 0xc00008a590, CONNECTING
INFO[0002] Channel Connectivity change to CONNECTING
INFO[0002] lbBalancer: handle SubConn state change: 0xc00008a5f0, CONNECTING
INFO[0002] Subchannel picks a new address "127.0.0.1:8021" to connect
INFO[0002] Subchannel Connectivity change to READY
INFO[0002] lbBalancer: handle SubConn state change: 0xc00008a590, READY
INFO[0002] Channel Connectivity change to READY
INFO[0002] Subchannel Connectivity change to READY
INFO[0002] lbBalancer: handle SubConn state change: 0xc00008a5f0, READY
2020/04/16 15:37:47 Greeting: Hello world from server-8021
2020/04/16 15:37:48 Greeting: Hello world from server-8011
2020/04/16 15:37:49 Greeting: Hello world from server-8021
2020/04/16 15:37:50 Greeting: Hello world from server-8011
2020/04/16 15:37:51 Greeting: Hello world from server-8021
2020/04/16 15:37:52 Greeting: Hello world from server-8011
2020/04/16 15:37:53 Greeting: Hello world from server-8021
2020/04/16 15:37:54 Greeting: Hello world from server-8011
2020/04/16 15:37:55 Greeting: Hello world from server-8021
2020/04/16 15:37:56 Greeting: Hello world from server-8011
INFO[0012] lbBalancer: processing server list: servers: servers:
INFO[0012] lbBalancer: server list entry[0]: ipStr:|127.0.0.1|, port:|8020|, load balancer token:||
INFO[0012] lbBalancer: server list entry[1]: ipStr:|127.0.0.1|, port:|8010|, load balancer token:||
2020/04/16 15:37:57 Greeting: Hello world from server-8020
2020/04/16 15:37:58 Greeting: Hello world from server-8010
2020/04/16 15:37:59 Greeting: Hello world from server-8020
2020/04/16 15:38:00 Greeting: Hello world from server-8010
2020/04/16 15:38:01 Greeting: Hello world from server-8020
2020/04/16 15:38:02 Greeting: Hello world from server-8010
2020/04/16 15:38:03 Greeting: Hello world from server-8020
2020/04/16 15:38:04 Greeting: Hello world from server-8010
2020/04/16 15:38:05 Greeting: Hello world from server-8020
2020/04/16 15:38:06 Greeting: Hello world from server-8010
INFO[0022] lbBalancer: processing server list: servers: servers:
INFO[0022] lbBalancer: server list entry[0]: ipStr:|127.0.0.1|, port:|8021|, load balancer token:||
INFO[0022] lbBalancer: server list entry[1]: ipStr:|127.0.0.1|, port:|8011|, load balancer token:||
2020/04/16 15:38:07 Greeting: Hello world from server-8011
2020/04/16 15:38:08 Greeting: Hello world from server-8021
2020/04/16 15:38:09 Greeting: Hello world from server-8011
結論
クライアントはカスタムresolver解析を適用します」whatever:///this-gets-overwritten
{Addr: "127.0.0.1:8888", Type: resolver.GRPCLB}
を取得し、grpclbであることを知り、load_を押した.balancer.protoの定義クエリーjawlbは、バックエンドアドレスリストを取得します.JAwlbは10 sごとにサーバリストを更新し,複数のアドレスを出力する.クライアントは、複数のアドレス間で要求を交代します.
その他のテスト
λ client
INFO[0000] parsed scheme: "whatever"
INFO[0000] ccResolverWrapper: sending update to cc: {[{127.0.0.1:8888 1 }] }
INFO[0000] ClientConn switching balancer to "grpclb"
INFO[0000] Channel switches to new LB policy "grpclb"
INFO[0000] lbBalancer: UpdateClientConnState: {ResolverState:{Addresses:[{Addr:127.0.0.1:8888 ServerName: Attributes: Type:1 Metadata:}] ServiceConfig: Attributes:} BalancerConfig:}
INFO[0000] parsed scheme: "grpclb-internal"
INFO[0000] ccResolverWrapper: sending update to cc: {[{127.0.0.1:8888 0 }] }
INFO[0000] ClientConn switching balancer to "pick_first"
INFO[0000] Channel switches to new LB policy "pick_first"
INFO[0000] Subchannel Connectivity change to CONNECTING
INFO[0000] blockingPicker: the picked transport is not ready, loop back to repick
INFO[0000] pickfirstBalancer: HandleSubConnStateChange: 0xc00003fb10, {CONNECTING }
INFO[0000] Channel Connectivity change to CONNECTING
INFO[0000] Subchannel picks a new address "127.0.0.1:8888" to connect
INFO[0000] CPU time info is unavailable on non-linux or appengine environment.
INFO[0000] Subchannel Connectivity change to READY
INFO[0000] pickfirstBalancer: HandleSubConnStateChange: 0xc00003fb10, {READY }
INFO[0000] Channel Connectivity change to READY
INFO[0000] lbBalancer: processing server list: servers: servers:
INFO[0000] lbBalancer: server list entry[0]: ipStr:|127.0.0.1|, port:|8010|, load balancer token:||
INFO[0000] lbBalancer: server list entry[1]: ipStr:|127.0.0.1|, port:|8020|, load balancer token:||
INFO[0000] Subchannel Connectivity change to CONNECTING
INFO[0000] Subchannel Connectivity change to CONNECTING
INFO[0000] Channel Connectivity change to TRANSIENT_FAILURE
INFO[0000] lbBalancer: handle SubConn state change: 0xc00008a220, CONNECTING
INFO[0000] Channel Connectivity change to CONNECTING
INFO[0000] lbBalancer: handle SubConn state change: 0xc00008a280, CONNECTING
2020/04/16 16:40:06 could not greet: rpc error: code = Unavailable desc = all SubConns are in TransientFailure