Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
GRPC load balancing sample in Go
syntax = "proto3";
package clibalance;
service Balanceable {
rpc Relay(Ping) returns (Pong);
}
message Ping {
int64 id = 1;
}
message Pong {
int64 id = 1;
}
package main
import (
"context"
"fmt"
"log"
"net"
"os"
"strconv"
"time"
"client-balance/clibalance"
"github.com/sercand/kuberesolver"
"google.golang.org/grpc"
"google.golang.org/grpc/balancer/roundrobin"
"google.golang.org/grpc/resolver"
"google.golang.org/grpc/resolver/manual"
)
type Server struct {
Port int
}
func (s *Server) Relay(ctx context.Context, req *clibalance.Ping) (*clibalance.Pong, error) {
log.Printf("[%d] relaying ping as pong: %d", s.Port, req.GetId())
return &clibalance.Pong{Id: req.Id}, nil
}
func main() {
if len(os.Args) < 2 {
fmt.Println("need arg")
return
}
switch os.Args[1] {
case "client":
svc := clientSetup()
for i := int64(0); true; i++ {
client(svc, i)
time.Sleep(250 * time.Millisecond)
}
case "server":
if len(os.Args) < 3 {
fmt.Println("server must also have port")
return
}
port, err := strconv.Atoi(os.Args[2])
if err != nil {
fmt.Println("port must be numeric")
return
}
server(port)
default:
fmt.Println("unsupported mode; try 'client' or 'server'")
}
}
func clientSetup() clibalance.BalanceableClient {
res, _ := manual.GenerateAndRegisterManualResolver()
res.InitialState(resolver.State{Addresses: []resolver.Address{
resolver.Address{Addr: "127.0.0.1:8080", Type: resolver.Backend},
resolver.Address{Addr: "127.0.0.1:8081", Type: resolver.Backend},
resolver.Address{Addr: "127.0.0.1:8082", Type: resolver.Backend},
}})
resolver.SetDefaultScheme(res.Scheme())
kuberesolver.RegisterInCluster()
conn, err := grpc.Dial("", grpc.WithInsecure(), grpc.WithBalancerName(roundrobin.Name))
if err != nil {
log.Fatalf("failed to dial: %v", err)
}
return clibalance.NewBalanceableClient(conn)
}
func client(svc clibalance.BalanceableClient, num int64) {
p, err := svc.Relay(context.Background(), &clibalance.Ping{Id: num})
if err != nil {
log.Printf("failed to relay: %v", err)
return
}
log.Printf("Pong! (%d)", p.GetId())
}
func server(port int) {
log.Printf("starting server on port %d", port)
lis, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
grpcServer := grpc.NewServer()
clibalance.RegisterBalanceableServer(grpcServer, &Server{Port: port})
grpcServer.Serve(lis)
}
@bmhatfield

This comment has been minimized.

Copy link
Owner Author

@bmhatfield bmhatfield commented Aug 11, 2020

To use this, you'll need to generate the protobuf file (using grpc-gen-go) into a clibalance sub-package so it can be imported.

You can then run multiple servers and a client, and then stop/start server processes to watch how the "pong" responses move around the "cluster".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.