grpc自带负载均衡实例

grpc 自带负载均衡

核心 : “google.golang.org/grpc/resolver”

bp

$ protoc -I ./ pb/*.proto —plugin=protoc-gen-go=protoc-gen-go —go_out=plugins=grpc:pb
syntax = "proto3";
option go_package = "./echo";
package echo;
// Request
message EchoRequest {
  string message = 1;
}
// Response
message EchoResponse {
  string message = 1;
}
// Echo is the echo service.
service Echo {
  // UnaryEcho is unary echo.
  rpc UnaryEcho(EchoRequest) returns (EchoResponse) {}
  // ServerStreamingEcho is server side streaming.
  rpc ServerStreamingEcho(EchoRequest) returns (stream EchoResponse) {}
  // ClientStreamingEcho is client side streaming.
  rpc ClientStreamingEcho(stream EchoRequest) returns (EchoResponse) {}
  // BidirectionalStreamingEcho is bidi streaming.
  rpc BidirectionalStreamingEcho(stream EchoRequest) returns (stream EchoResponse) {}
}

server端

package main

import (
	"context"
	"fmt"
	"go_script/grpc_2/pb/echo"
	"google.golang.org/grpc"
	"log"
	"net"
	"sync"
)

var (
	addrs = []string{":50051", ":50052", ":50053", ":50054"}
)

type ecServer struct {
	echo.UnimplementedEchoServer
	addr string
}

func (s *ecServer) UnaryEcho(ctx context.Context, req *echo.EchoRequest) (*echo.EchoResponse, error) {
	log.Println(req.Message, s.addr)
	return &echo.EchoResponse{Message: fmt.Sprintf("%s (from %s)", req.Message, s.addr)}, nil
}

// 启动grpc服务
func startServer(addr string) {
	lis, err := net.Listen("tcp", addr)
	if err != nil {
		log.Fatalf("failed to listen: %v", err)
	}
	s := grpc.NewServer()
	echo.RegisterEchoServer(s, &ecServer{addr: addr})
	log.Printf("serving on %s\n", addr)
	if err := s.Serve(lis); err != nil {
		log.Fatalf("failed to serve: %v", err)
	}
}

func main() {
	var wg sync.WaitGroup
	for _, addr := range addrs {
		wg.Add(1)
		go func(addr string) {
			defer wg.Done()
			startServer(addr)
		}(addr)
	}
	wg.Wait()
}

client端

package main

import (
	"context"
	"fmt"
	"go_script/grpc_2/pb/echo"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
	"google.golang.org/grpc/resolver"
	"log"
	"time"
)

const (
	Scheme      = "scheme"
	ServiceName = "service_name"
)

var addrs = []string{"localhost:50051", "localhost:50052", "localhost:50053", "localhost:50054"}

// 负载均衡实现
type ResolverBuilder struct{}

func (*ResolverBuilder) Build(target resolver.Target, cc resolver.ClientConn, opts resolver.BuildOptions) (resolver.Resolver, error) {
	r := &exampleResolver{
		target: target,
		cc:     cc,
		addrsStore: map[string][]string{
			ServiceName: addrs,
		},
	}
	r.start()
	return r, nil
}
func (*ResolverBuilder) Scheme() string { return Scheme }

type exampleResolver struct {
	target     resolver.Target
	cc         resolver.ClientConn
	addrsStore map[string][]string
}

func (r *exampleResolver) start() {
	addrStrs := r.addrsStore[r.target.Endpoint]
	addrs := make([]resolver.Address, len(addrStrs))
	for i, s := range addrStrs {
		addrs[i] = resolver.Address{Addr: s}
	}
	r.cc.UpdateState(resolver.State{Addresses: addrs})
}
func (*exampleResolver) ResolveNow(o resolver.ResolveNowOptions) {}
func (*exampleResolver) Close()                                  {}

func init() {
	resolver.Register(&ResolverBuilder{})
}



func main() {

	roundrobinConn, err := grpc.Dial(
		fmt.Sprintf("%s:///%s", Scheme, ServiceName),
		
		grpc.WithDefaultServiceConfig(`{"loadBalancingConfig": [{"round_robin":{}}]}`), // https://github.com/grpc/grpc/blob/master/doc/service_config.md
		grpc.WithTransportCredentials(insecure.NewCredentials()),
	)
	if err != nil {
		log.Fatalf("did not connect: %v", err)
	}
	defer roundrobinConn.Close()

	fmt.Println("--- calling helloworld.Greeter/SayHello with round_robin ---")
	hwc := echo.NewEchoClient(roundrobinConn)
	for i := 0; i < 20; i++ {
		callUnaryEcho(hwc, "this is load_balancing")
	}
}

func callUnaryEcho(c echo.EchoClient, message string) {
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	r, err := c.UnaryEcho(ctx, &echo.EchoRequest{Message: message})
	if err != nil {
		log.Fatalf("could not greet: %v", err)
	}
	fmt.Println(r.Message)
}

代码地址

https://github.com/mangenotwork/man/tree/master/core/grpc_2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值