基本介绍

负载均衡组件使用在客户端中。 GoFrame 框架提供了解耦化设计的、灵活性高、扩展性强的负载均衡组件,由 gsel 组件管理,该组件定义了负载均衡的接口,并提供了多种内置的负载均衡策略实现。开发者也可以根据接口实现自定义的负载均衡策略。

策略列表

gsel 组件提供了多种常用的负载均衡策略,供开发者选择使用:

策略名称策略描述
LeastConnection最小连接数。
Random随机访问。
RoundRobin轮训访问。
Weight权重访问。服务注册时需要设置 Weight 参数。

使用示例

HTTP

server.go

  1. package main
  2. import (
  3. "github.com/gogf/gf/contrib/registry/etcd/v2"
  4. "github.com/gogf/gf/v2/frame/g"
  5. "github.com/gogf/gf/v2/net/ghttp"
  6. "github.com/gogf/gf/v2/net/gsvc"
  7. )
  8. func main() {
  9. gsvc.SetRegistry(etcd.New(`127.0.0.1:2379`))
  10. s := g.Server(`hello.svc`)
  11. s.BindHandler("/", func(r *ghttp.Request) {
  12. g.Log().Info(r.Context(), `request received`)
  13. r.Response.Write(`Hello world`)
  14. })
  15. s.Run()
  16. }

client.go

这里使用 gsel.SetBuilder(gsel.NewBuilderRoundRobin()) 设置全局的负载均衡策略为轮训访问策略。

  1. package main
  2. import (
  3. "github.com/gogf/gf/contrib/registry/etcd/v2"
  4. "github.com/gogf/gf/v2/frame/g"
  5. "github.com/gogf/gf/v2/net/gsel"
  6. "github.com/gogf/gf/v2/net/gsvc"
  7. "github.com/gogf/gf/v2/os/gctx"
  8. )
  9. func main() {
  10. gsvc.SetRegistry(etcd.New(`127.0.0.1:2379`))
  11. gsel.SetBuilder(gsel.NewBuilderRoundRobin())
  12. for i := 0; i < 10; i++ {
  13. ctx := gctx.New()
  14. res := g.Client().GetContent(ctx, `http://hello.svc/`)
  15. g.Log().Info(ctx, res)
  16. }
  17. }

分别启动两个服务端,并执行客户端。

server1 终端输出:

  1. $ go run server.go
  2. 2023-03-15 21:24:08.413 [INFO] pid[10219]: http server started listening on [:63956]
  3. 2023-03-15 21:24:08.413 [INFO] openapi specification is disabled
  4. 2023-03-15 21:24:08.413 [DEBU] service register: &{Head: Deployment: Namespace: Name:hello.svc Version: Endpoints:10.35.12.81:63956 Metadata:map[insecure:true protocol:http]}
  5. 2023-03-15 21:24:08.455 [DEBU] etcd put success with key "/service/default/default/hello.svc/latest/10.35.12.81:63956", value "{"insecure":true,"protocol":"http"}", lease "7587869265945813020"
  6. SERVER | DOMAIN | ADDRESS | METHOD | ROUTE | HANDLER | MIDDLEWARE
  7. ------------|---------|---------|--------|-------|-----------------------------------------------------------------|--------------------
  8. hello.svc | default | :63956 | ALL | / | main.main.func1 |
  9. ------------|---------|---------|--------|-------|-----------------------------------------------------------------|--------------------
  10. hello.svc | default | :63956 | ALL | /* | github.com/gogf/gf/v2/net/ghttp.internalMiddlewareServerTracing | GLOBAL MIDDLEWARE
  11. ------------|---------|---------|--------|-------|-----------------------------------------------------------------|--------------------
  12. 2023-03-15 21:24:18.357 [INFO] {e05b6049859a4c17d1de5d62eafa5a5f} request received
  13. 2023-03-15 21:24:18.358 [INFO] {785e9349859a4c17d3de5d62049e5b51} request received
  14. 2023-03-15 21:24:18.360 [INFO] {7076ab49859a4c17d5de5d62aaa64c85} request received
  15. 2023-03-15 21:24:18.360 [INFO] {205fb849859a4c17d7de5d62cb2590f4} request received
  16. 2023-03-15 21:24:18.361 [INFO] {885fc349859a4c17d9de5d6235937e31} request received

server2 终端输出:

  1. $ go run server.go
  2. 2023-03-15 21:24:10.769 [INFO] pid[10242]: http server started listening on [:63964]
  3. 2023-03-15 21:24:10.770 [INFO] openapi specification is disabled
  4. 2023-03-15 21:24:10.770 [DEBU] service register: &{Head: Deployment: Namespace: Name:hello.svc Version: Endpoints:10.35.12.81:63964 Metadata:map[insecure:true protocol:http]}
  5. 2023-03-15 21:24:10.812 [DEBU] etcd put success with key "/service/default/default/hello.svc/latest/10.35.12.81:63964", value "{"insecure":true,"protocol":"http"}", lease "7587869265945813023"
  6. SERVER | DOMAIN | ADDRESS | METHOD | ROUTE | HANDLER | MIDDLEWARE
  7. ------------|---------|---------|--------|-------|-----------------------------------------------------------------|--------------------
  8. hello.svc | default | :63964 | ALL | / | main.main.func1 |
  9. ------------|---------|---------|--------|-------|-----------------------------------------------------------------|--------------------
  10. hello.svc | default | :63964 | ALL | /* | github.com/gogf/gf/v2/net/ghttp.internalMiddlewareServerTracing | GLOBAL MIDDLEWARE
  11. ------------|---------|---------|--------|-------|-----------------------------------------------------------------|--------------------
  12. 2023-03-15 21:24:18.357 [INFO] {602d8749859a4c17d2de5d62d515e464} request received
  13. 2023-03-15 21:24:18.359 [INFO] {e0ed9b49859a4c17d4de5d628284ae62} request received
  14. 2023-03-15 21:24:18.360 [INFO] {e0e0b249859a4c17d6de5d62beda3001} request received
  15. 2023-03-15 21:24:18.361 [INFO] {7087bd49859a4c17d8de5d62f892e8aa} request received
  16. 2023-03-15 21:24:18.361 [INFO] {e8aec849859a4c17dade5d6247101836} request received

客户端终端输出:

  1. $ go run client.go
  2. 2023-03-15 21:24:18.357 [INFO] {e05b6049859a4c17d1de5d62eafa5a5f} Hello world
  3. 2023-03-15 21:24:18.358 [INFO] {602d8749859a4c17d2de5d62d515e464} Hello world
  4. 2023-03-15 21:24:18.358 [INFO] {785e9349859a4c17d3de5d62049e5b51} Hello world
  5. 2023-03-15 21:24:18.359 [INFO] {e0ed9b49859a4c17d4de5d628284ae62} Hello world
  6. 2023-03-15 21:24:18.360 [INFO] {7076ab49859a4c17d5de5d62aaa64c85} Hello world
  7. 2023-03-15 21:24:18.360 [INFO] {e0e0b249859a4c17d6de5d62beda3001} Hello world
  8. 2023-03-15 21:24:18.360 [INFO] {205fb849859a4c17d7de5d62cb2590f4} Hello world
  9. 2023-03-15 21:24:18.361 [INFO] {7087bd49859a4c17d8de5d62f892e8aa} Hello world
  10. 2023-03-15 21:24:18.361 [INFO] {885fc349859a4c17d9de5d6235937e31} Hello world
  11. 2023-03-15 21:24:18.361 [INFO] {e8aec849859a4c17dade5d6247101836} Hello world

GRPC

server.go

  1. package main
  2. import (
  3. "github.com/gogf/gf/contrib/rpc/grpcx/v2"
  4. "github.com/gogf/gf/example/rpc/grpcx/balancer/controller"
  5. )
  6. func main() {
  7. s := grpcx.Server.New()
  8. controller.Register(s)
  9. s.Run()
  10. }

client.go

  1. package main
  2. import (
  3. "context"
  4. "github.com/gogf/gf/contrib/rpc/grpcx/v2"
  5. "github.com/gogf/gf/example/rpc/grpcx/balancer/protobuf"
  6. "github.com/gogf/gf/v2/frame/g"
  7. "github.com/gogf/gf/v2/os/gctx"
  8. )
  9. func main() {
  10. var (
  11. ctx context.Context
  12. conn = grpcx.Client.MustNewGrpcClientConn("demo", grpcx.Balancer.WithRandom())
  13. client = protobuf.NewGreeterClient(conn)
  14. )
  15. for i := 0; i < 10; i++ {
  16. ctx = gctx.New()
  17. res, err := client.SayHello(ctx, &protobuf.HelloRequest{Name: "World"})
  18. if err != nil {
  19. g.Log().Error(ctx, err)
  20. return
  21. }
  22. g.Log().Debug(ctx, "Response:", res.Message)
  23. }
  24. }

其中的 grpcx.Balancer.WithRandom() 表示使用随机的请求策略。启动两个 server.go 服务端,随后运行 client.go 客户端,查看服务端的请求日志:

server1 终端输出:

  1. $ go run server.go
  2. 2023-03-15 19:50:44.801 [DEBU] set default registry using file registry as no custom registry set
  3. 2023-03-15 19:50:44.802 [DEBU] service register: &{Head: Deployment: Namespace: Name:demo Version: Endpoints:10.35.12.81:53962 Metadata:map[protocol:grpc]}
  4. 2023-03-15 19:50:44.802 [INFO] pid[89290]: grpc server started listening on [:53962]
  5. 2023-03-15 19:50:57.282 {7025612f6d954c17c5f335051bf10899} /protobuf.Greeter/SayHello, 0.003ms, name:"World", message:"Hello World"
  6. 2023-03-15 19:50:57.283 {60567c2f6d954c17c7f335052ce05185} /protobuf.Greeter/SayHello, 0.002ms, name:"World", message:"Hello World"
  7. 2023-03-15 19:50:57.285 {f8d09b2f6d954c17ccf33505dff1a4ea} /protobuf.Greeter/SayHello, 0.002ms, name:"World", message:"Hello World"
  8. 2023-03-15 19:50:57.287 {f0fab02f6d954c17cdf33505438b2c80} /protobuf.Greeter/SayHello, 0.001ms, name:"World", message:"Hello World"

server2 终端输出:

  1. $ go run server.go
  2. 2023-03-15 19:50:51.720 [DEBU] set default registry using file registry as no custom registry set
  3. 2023-03-15 19:50:51.721 [DEBU] service register: &{Head: Deployment: Namespace: Name:demo Version: Endpoints:10.35.12.81:53973 Metadata:map[protocol:grpc]}
  4. 2023-03-15 19:50:51.722 [INFO] pid[89351]: grpc server started listening on [:53973]
  5. 2023-03-15 19:50:57.280 {b89a0d2f6d954c17c4f33505a046817c} /protobuf.Greeter/SayHello, 0.002ms, name:"World", message:"Hello World"
  6. 2023-03-15 19:50:57.282 {28bf732f6d954c17c6f33505adedff5f} /protobuf.Greeter/SayHello, 0.002ms, name:"World", message:"Hello World"
  7. 2023-03-15 19:50:57.283 {9876832f6d954c17c8f3350580ed535b} /protobuf.Greeter/SayHello, 0.002ms, name:"World", message:"Hello World"
  8. 2023-03-15 19:50:57.284 {684e8b2f6d954c17c9f33505d56e4b05} /protobuf.Greeter/SayHello, 0.001ms, name:"World", message:"Hello World"
  9. 2023-03-15 19:50:57.284 {c045912f6d954c17caf3350599006197} /protobuf.Greeter/SayHello, 0.001ms, name:"World", message:"Hello World"
  10. 2023-03-15 19:50:57.284 {500a972f6d954c17cbf33505252b0e01} /protobuf.Greeter/SayHello, 0.001ms, name:"World", message:"Hello World"

客户端终端输出:

  1. $ go run client.go
  2. 2023-03-15 19:50:57.278 [DEBU] client conn updated with addresses [{"Addr":"10.35.12.81:53962","ServerName":"demo","Attributes":{},"BalancerAttributes":null,"Type":0,"Metadata":null},{"Addr":"10.35.12.81:53973","ServerName":"demo","Attributes":{},"BalancerAttributes":null,"Type":0,"Metadata":null}]
  3. 2023-03-15 19:50:57.281 [DEBU] {b89a0d2f6d954c17c4f33505a046817c} Response: Hello World
  4. 2023-03-15 19:50:57.282 [DEBU] {7025612f6d954c17c5f335051bf10899} Response: Hello World
  5. 2023-03-15 19:50:57.282 [DEBU] {28bf732f6d954c17c6f33505adedff5f} Response: Hello World
  6. 2023-03-15 19:50:57.283 [DEBU] {60567c2f6d954c17c7f335052ce05185} Response: Hello World
  7. 2023-03-15 19:50:57.283 [DEBU] {9876832f6d954c17c8f3350580ed535b} Response: Hello World
  8. 2023-03-15 19:50:57.284 [DEBU] {684e8b2f6d954c17c9f33505d56e4b05} Response: Hello World
  9. 2023-03-15 19:50:57.284 [DEBU] {c045912f6d954c17caf3350599006197} Response: Hello World
  10. 2023-03-15 19:50:57.285 [DEBU] {500a972f6d954c17cbf33505252b0e01} Response: Hello World
  11. 2023-03-15 19:50:57.286 [DEBU] {f8d09b2f6d954c17ccf33505dff1a4ea} Response: Hello World
  12. 2023-03-15 19:50:57.287 [DEBU] {f0fab02f6d954c17cdf33505438b2c80} Response: Hello World