九卷技术录

V1

2023/05/05阅读:24主题:简

Go微服务框架go-kratos实战学习08:负载均衡基本使用

微服务框架 go-kratos 中负载均衡使用

一、介绍

在前面这篇文章 负载均衡和它的算法介绍,讲了什么是负载均衡以及作用、算法介绍。

go-kratos 的负载均衡主要接口是 Selector,它是一个可插拔的设计。因为它设计的都是接口,只要实现了接口就实现了负载均衡。

go-kratos 在目录下提供了一个默认的 Selector 实现,default_node.godefault_selector.go

你可以自定义程序来替换这个默认实现。可以通过替换 NodeBuilder 实现节点权重计算算法,Filter 实现服务路由过滤策,Balancer 来实现负载均衡算法。

go-kratos 负载均衡结构主要组成:

image-20230403183123409
image-20230403183123409

在 go-kratos 中已支持 3 种负载均衡算法,分别是:

  • wrr : Weighted round robin (Kratos Client内置默认算法),权重轮询算法
  • p2c : Power of two choices
  • random : Random,随机算法

二、基本使用

go-kratos 负载均衡有2个使用,一个是 http ,一个是 gRPC。

go-kratos 文档中展示了主要代码。

go-kratos v2.6.1

go v1.20.2

示例代码在 go-kratosexamples 中的 Selector。

从上面例子中摘出 grpc 负载均衡例子,代码如下:

client/grpc.go

package main

import (
 "context"
 "log"
 "time"

 "github.com/go-kratos/kratos/contrib/registry/consul/v2"
 "github.com/go-kratos/v2/selector/filter"
 "github.com/go-kratos/v2/selector/wrr"
 "github.com/go-kratos/v2/transport/grpc"
 "github.com/hashicorp/consul/api"
 "gitub.com/go-kratos/examples/helloworld/helloworld"
)

func main() {
 consulCli, err := api.NewClient(api.DefaultConfig())
 if err != nil {
  panic(err)
 }

 r := consul.New(consulCli)

 // grpc client
 conn, err := grpc.DialInsecure(
  context.Background(),
  grpc.WithEndpoint("discovery:///helloworld"),
  grpc.WithDiscovery(r), // consul作为服务发现中心
  // 负载均衡 和 filter,weighted round robin算法
  grpc.WithBalancerName(wrr.Name),
  grpc.WithFilter(
   filter.Version("1.0.0"), //静态version=1.0.0的Filter
  ),
 )
 if err != nil {
  log.Fatal(err)
 }
 defer conn.Close()
 gClient := helloworld.NewGreeterClient(conn)

 for {
  time.Sleep(time.Second)

  CallGRPC(gClient)
 }
}

func CallGRPC(client helloworld.NewGreeterClient) {
 reply, err := client.SayHello(context.Background(), &helloworld.HelloRequest{Name: "go-kratos"})
 if err != nil {
  log.Fatal(err)
 }
 log.Printf("[grpc] SayHello %+v \n", reply)
}

服务端,server/grpc.go

package main

import (
 "context"
 "fmt"
 "os"

 "github.com/go-kratos/examples/helloworld/helloworld"
 "github.com/go-kratos/kratos/contrib/registry/consul/v2"
 "github.com/go-kratos/kratos/v2"
 "github.com/go-kratos/kratos/v2/log"
 "github.com/go-kratos/kratos/v2/middleware/logging"
 "github.com/go-kratos/kratos/v2/middleware/recovery"
 "github.com/go-kratos/kratos/v2/transport/grpc"
 "github.com/hashicorp/consul/api"
)

type server struct {
 helloworld.UnimplementedGreeterServer
}

func (s *server) SayHello(ctx context.Context, in *helloworld.HelloRequest) (*helloworld.HelloReply, error) {
 return &helloworld.HelloReply{Message: fmt.Sprintf("welcome %+v!", in.Name)}, nil
}

func main() {
 logger := log.NewStdLogger(os.Stdout)

 consulClient, err := api.NewClient(api.DefaultConfig())
 if err != nil {
  log.NewHelper(logger).Fatal(err)
 }
 go runServer("1.0.0", logger, consulClient, 8000)
 go runServer("1.0.0", logger, consulClient, 8010)

 runServer("2.0.0", logger, consulClient, 8020)
}

func runServer(version string, logger log.Logger, client *api.Client, port int) {
 logger = log.With(logger, "version", version, "port:", port)
 log := log.NewHelper(logger)

 grpcSrv := grpc.NewServer(
  grpc.Address(fmt.Sprintf(":%d", port+1000)),
  grpc.Middleware(
   recovery.Recovery(),
   logging.Server(logger),
  ),
 )

 s := &server{}
 helloworld.RegisterGreeterServer(grpcSrv, s)

 r := consul.New(client)
 app := kratos.New(
  kratos.Name("helloworld"),
  kratos.Server(
   grpcSrv,
  ),
  kratos.Version(version),
  kratos.Registrar(r),
 )

 if err := app.Run(); err != nil {
  log.Fatal(err)
 }
}

也可以到我的公众号 九卷技术录:Go微服务框架go-kratos实战学习08:负载均衡基本使用 讨论

三、参考

  • https://github.com/go-kratos/kratos/blob/v2.6.1/selector/default_selector.go go-kratos v2.6.1 selector 默认实现
  • https://go-kratos.dev/docs/component/selector/ go-kratos 路由与负载均衡
  • https://github.com/go-kratos

分类:

后端

标签:

Golang

作者介绍

九卷技术录
V1

好技术成就你我[公号:九卷技术录]