基本介绍

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

策略列表

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

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

使用示例

HTTP

server.go

package main

import (
	"github.com/gogf/gf/contrib/registry/etcd/v2"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/net/ghttp"
	"github.com/gogf/gf/v2/net/gsvc"
)

func main() {
	gsvc.SetRegistry(etcd.New(`127.0.0.1:2379`))

	s := g.Server(`hello.svc`)
	s.BindHandler("/", func(r *ghttp.Request) {
		g.Log().Info(r.Context(), `request received`)
		r.Response.Write(`Hello world`)
	})
	s.Run()
}

client.go

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

package main

import (
	"github.com/gogf/gf/contrib/registry/etcd/v2"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/net/gsel"
	"github.com/gogf/gf/v2/net/gsvc"
	"github.com/gogf/gf/v2/os/gctx"
)

func main() {
	gsvc.SetRegistry(etcd.New(`127.0.0.1:2379`))
	gsel.SetBuilder(gsel.NewBuilderRoundRobin())

	for i := 0; i < 10; i++ {
		ctx := gctx.New()
		res := g.Client().GetContent(ctx, `http://hello.svc/`)
		g.Log().Info(ctx, res)
	}
}

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

server1终端输出:

$ go run server.go
2023-03-15 21:24:08.413 [INFO] pid[10219]: http server started listening on [:63956]
2023-03-15 21:24:08.413 [INFO] openapi specification is disabled
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]}
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"

   SERVER   | DOMAIN  | ADDRESS | METHOD | ROUTE |                             HANDLER                             |    MIDDLEWARE      
------------|---------|---------|--------|-------|-----------------------------------------------------------------|--------------------
  hello.svc | default | :63956  | ALL    | /     | main.main.func1                                                 |                    
------------|---------|---------|--------|-------|-----------------------------------------------------------------|--------------------
  hello.svc | default | :63956  | ALL    | /*    | github.com/gogf/gf/v2/net/ghttp.internalMiddlewareServerTracing | GLOBAL MIDDLEWARE  
------------|---------|---------|--------|-------|-----------------------------------------------------------------|--------------------

2023-03-15 21:24:18.357 [INFO] {e05b6049859a4c17d1de5d62eafa5a5f} request received
2023-03-15 21:24:18.358 [INFO] {785e9349859a4c17d3de5d62049e5b51} request received
2023-03-15 21:24:18.360 [INFO] {7076ab49859a4c17d5de5d62aaa64c85} request received
2023-03-15 21:24:18.360 [INFO] {205fb849859a4c17d7de5d62cb2590f4} request received
2023-03-15 21:24:18.361 [INFO] {885fc349859a4c17d9de5d6235937e31} request received

server2终端输出:

$ go run server.go 
2023-03-15 21:24:10.769 [INFO] pid[10242]: http server started listening on [:63964]
2023-03-15 21:24:10.770 [INFO] openapi specification is disabled
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]}
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"

   SERVER   | DOMAIN  | ADDRESS | METHOD | ROUTE |                             HANDLER                             |    MIDDLEWARE      
------------|---------|---------|--------|-------|-----------------------------------------------------------------|--------------------
  hello.svc | default | :63964  | ALL    | /     | main.main.func1                                                 |                    
------------|---------|---------|--------|-------|-----------------------------------------------------------------|--------------------
  hello.svc | default | :63964  | ALL    | /*    | github.com/gogf/gf/v2/net/ghttp.internalMiddlewareServerTracing | GLOBAL MIDDLEWARE  
------------|---------|---------|--------|-------|-----------------------------------------------------------------|--------------------

2023-03-15 21:24:18.357 [INFO] {602d8749859a4c17d2de5d62d515e464} request received
2023-03-15 21:24:18.359 [INFO] {e0ed9b49859a4c17d4de5d628284ae62} request received
2023-03-15 21:24:18.360 [INFO] {e0e0b249859a4c17d6de5d62beda3001} request received
2023-03-15 21:24:18.361 [INFO] {7087bd49859a4c17d8de5d62f892e8aa} request received
2023-03-15 21:24:18.361 [INFO] {e8aec849859a4c17dade5d6247101836} request received

客户端终端输出:

$ go run client.go  
2023-03-15 21:24:18.357 [INFO] {e05b6049859a4c17d1de5d62eafa5a5f} Hello world
2023-03-15 21:24:18.358 [INFO] {602d8749859a4c17d2de5d62d515e464} Hello world
2023-03-15 21:24:18.358 [INFO] {785e9349859a4c17d3de5d62049e5b51} Hello world
2023-03-15 21:24:18.359 [INFO] {e0ed9b49859a4c17d4de5d628284ae62} Hello world
2023-03-15 21:24:18.360 [INFO] {7076ab49859a4c17d5de5d62aaa64c85} Hello world
2023-03-15 21:24:18.360 [INFO] {e0e0b249859a4c17d6de5d62beda3001} Hello world
2023-03-15 21:24:18.360 [INFO] {205fb849859a4c17d7de5d62cb2590f4} Hello world
2023-03-15 21:24:18.361 [INFO] {7087bd49859a4c17d8de5d62f892e8aa} Hello world
2023-03-15 21:24:18.361 [INFO] {885fc349859a4c17d9de5d6235937e31} Hello world
2023-03-15 21:24:18.361 [INFO] {e8aec849859a4c17dade5d6247101836} Hello world

GRPC

server.go

package main

import (
	"github.com/gogf/gf/contrib/rpc/grpcx/v2"
	"github.com/gogf/gf/example/rpc/grpcx/balancer/controller"
)

func main() {
	s := grpcx.Server.New()
	controller.Register(s)
	s.Run()
}

client.go

package main

import (
	"context"

	"github.com/gogf/gf/contrib/rpc/grpcx/v2"
	"github.com/gogf/gf/example/rpc/grpcx/balancer/protobuf"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/gctx"
)

func main() {
	var (
		ctx    context.Context
		conn   = grpcx.Client.MustNewGrpcClientConn("demo", grpcx.Balancer.WithRandom())
		client = protobuf.NewGreeterClient(conn)
	)
	for i := 0; i < 10; i++ {
		ctx = gctx.New()
		res, err := client.SayHello(ctx, &protobuf.HelloRequest{Name: "World"})
		if err != nil {
			g.Log().Error(ctx, err)
			return
		}
		g.Log().Debug(ctx, "Response:", res.Message)
	}
}

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

server1终端输出:

$ go run server.go 
2023-03-15 19:50:44.801 [DEBU] set default registry using file registry as no custom registry set
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]}
2023-03-15 19:50:44.802 [INFO] pid[89290]: grpc server started listening on [:53962]
2023-03-15 19:50:57.282 {7025612f6d954c17c5f335051bf10899} /protobuf.Greeter/SayHello, 0.003ms, name:"World", message:"Hello World"
2023-03-15 19:50:57.283 {60567c2f6d954c17c7f335052ce05185} /protobuf.Greeter/SayHello, 0.002ms, name:"World", message:"Hello World"
2023-03-15 19:50:57.285 {f8d09b2f6d954c17ccf33505dff1a4ea} /protobuf.Greeter/SayHello, 0.002ms, name:"World", message:"Hello World"
2023-03-15 19:50:57.287 {f0fab02f6d954c17cdf33505438b2c80} /protobuf.Greeter/SayHello, 0.001ms, name:"World", message:"Hello World"

server2终端输出:

$ go run server.go 
2023-03-15 19:50:51.720 [DEBU] set default registry using file registry as no custom registry set
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]}
2023-03-15 19:50:51.722 [INFO] pid[89351]: grpc server started listening on [:53973]
2023-03-15 19:50:57.280 {b89a0d2f6d954c17c4f33505a046817c} /protobuf.Greeter/SayHello, 0.002ms, name:"World", message:"Hello World"
2023-03-15 19:50:57.282 {28bf732f6d954c17c6f33505adedff5f} /protobuf.Greeter/SayHello, 0.002ms, name:"World", message:"Hello World"
2023-03-15 19:50:57.283 {9876832f6d954c17c8f3350580ed535b} /protobuf.Greeter/SayHello, 0.002ms, name:"World", message:"Hello World"
2023-03-15 19:50:57.284 {684e8b2f6d954c17c9f33505d56e4b05} /protobuf.Greeter/SayHello, 0.001ms, name:"World", message:"Hello World"
2023-03-15 19:50:57.284 {c045912f6d954c17caf3350599006197} /protobuf.Greeter/SayHello, 0.001ms, name:"World", message:"Hello World"
2023-03-15 19:50:57.284 {500a972f6d954c17cbf33505252b0e01} /protobuf.Greeter/SayHello, 0.001ms, name:"World", message:"Hello World"

客户端终端输出:

$ go run client.go  
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}]
2023-03-15 19:50:57.281 [DEBU] {b89a0d2f6d954c17c4f33505a046817c} Response: Hello World
2023-03-15 19:50:57.282 [DEBU] {7025612f6d954c17c5f335051bf10899} Response: Hello World
2023-03-15 19:50:57.282 [DEBU] {28bf732f6d954c17c6f33505adedff5f} Response: Hello World
2023-03-15 19:50:57.283 [DEBU] {60567c2f6d954c17c7f335052ce05185} Response: Hello World
2023-03-15 19:50:57.283 [DEBU] {9876832f6d954c17c8f3350580ed535b} Response: Hello World
2023-03-15 19:50:57.284 [DEBU] {684e8b2f6d954c17c9f33505d56e4b05} Response: Hello World
2023-03-15 19:50:57.284 [DEBU] {c045912f6d954c17caf3350599006197} Response: Hello World
2023-03-15 19:50:57.285 [DEBU] {500a972f6d954c17cbf33505252b0e01} Response: Hello World
2023-03-15 19:50:57.286 [DEBU] {f8d09b2f6d954c17ccf33505dff1a4ea} Response: Hello World
2023-03-15 19:50:57.287 [DEBU] {f0fab02f6d954c17cdf33505438b2c80} Response: Hello World












Content Menu

  • No labels

2 Comments

  1. lin

    这里的负载均衡有点问题,场景如下, A机器上部署了两个RPC,B机器上部署了一个RPC

    RPC : A , A,  B

    RPC-CLIENT: A

    我设置了 负载均衡,但是rpc流量都往同一台机器A上走,B根本就收不到流量,除非把A的RPC下线了

    gsel.SetBuilder(gsel.NewBuilderRoundRobin())
    client := info.NewInfoClient(grpcx.Client.MustNewGrpcClientConn("default", grpcx.Balancer.WithRandom()))

    然后不知道哪里来的404,一直在写日志

    2023-09-04 22:55:17.892 {a4201cbf5f7cea7394b205b8e4aa57cd} 404 "PRI http  * HTTP/2.0" 0.000, 192.168.100.145, "", ""
    2023-09-04 22:55:19.267 {3394afa1d256d8278831ced6388fe642} 404 "PRI http  * HTTP/2.0" 0.000, 192.168.100.145, "", ""
    2023-09-04 22:56:10.067 {c61f14c0a9666fb497d505238f0392c7} 404 "PRI http  * HTTP/2.0" 0.001, 192.168.100.145, "", ""
    2023-09-04 22:56:26.350 {2a1f66d6befee58e27d8144352d944cb} 404 "PRI http  * HTTP/2.0" 0.000, 192.168.100.145, "", ""

    郭强 可以帮忙解释一下么

  2. lzx

    grpc权重访问如何设置weight参数?