This is a creation in Article, where the information may have evolved or changed.
The GRPC-LB uses client-side in-process load balancing, supports random, polling, consistent hash three load balancing policies, and supports server-side weighting. You can use ETCD or consul as a registry.
Project Address:
Https://github.com/liyue201/grpc-lb
Basic architecture, service providers get up and register their information with the registry, IP, ports, weights, and so on, and keep the heartbeat. The client listens to the registry, gets a list of servers, and updates the local server list as soon as the server changes. Each client request is accessed through a load balancing policy that chooses an appropriate server.
Example of a random load balancer client:
Package Mainimport ( etcd "github.com/coreos/etcd/client" grpclb "github.com/ liyue201/grpc-lb " " Github.com/liyue201/grpc-lb/examples/proto " registry" Github.com/liyue201/grpc-lb/registry/etcd " " Golang.org/x/net/context " " Google.golang.org/grpc " " log ") func main () { etcdconfg: = Etcd. config{ endpoints: []string{"http://120.24.44.201:4001"}, } r: = registry. Newresolver ("/grpc-lb", "Test", Etcdconfg) b: = grpclb. Newbalancer (R, GRPCLB. Newrandomselector ()) c, err: = Grpc. Dial ("", Grpc. Withinsecure (), Grpc. Withbalancer (b)) if Err! = Nil { log. Printf ("Grpc Dial:%s", err) return } defer C . Close () clienT: = Proto. Newtestclient (c) resp, err: = client. Say (context. Background (), &proto. Sayreq{content: "Random"}) if err! = Nil { log. PRINTLN (Err) return } log. Printf (resp. Content)}
Poll for load balancing, just change the newrandomselector to Newroundrobinselector.
Package Mainimport ( etcd "github.com/coreos/etcd/client" grpclb "github.com/ liyue201/grpc-lb " " Github.com/liyue201/grpc-lb/examples/proto " registry" Github.com/liyue201/grpc-lb/registry/etcd " " Golang.org/x/net/context " " Google.golang.org/grpc " " log ") func main () { etcdconfg: = Etcd. config{ endpoints: []string{"http://120.24.44.201:4001"}, } r: = registry. Newresolver ("/grpc-lb", "Test", Etcdconfg) b: = grpclb. Newbalancer (R, GRPCLB. Newroundrobinselector ()) c, err: = Grpc. Dial ("", Grpc. Withinsecure (), Grpc. Withbalancer (b)) if Err! = Nil { log. Printf ("Grpc Dial:%s", err) return } defer C . Close () cLient: = Proto. Newtestclient (c) resp, err: = client. Say (context. Background (), &proto. Sayreq{content: "Round Robin"}) if err! = Nil { log. PRINTLN (Err) return } log. Printf (resp. Content)}
Consistent hash load balancing requires a hash parameter for each request, depending on the scenario, which is the hashdata in the following example.
Package Mainimport ( FMT etcd "Github.com/coreos/etcd/client" &NBSP;GRPCLB "github.com/liyue201/grpc-lb" "Github.com/liyue201/grpc-lb/examples/proto" registry "GITHUB.COM/LIYUE201/GRPC-LB/REGISTRY/ETCD" "Golang.org/x/net/context" "Google.golang.org/grpc" "log" "Time") Func main () { &NBSP;ETCDCONFG: = Etcd. config{ endpoints: []string{"http://120.24.44.201:4001"}, } r: = registry. Newresolver ("/grpc-lb", "Test", Etcdconfg) b: = grpclb. Newbalancer (R, GRPCLB. Newketamaselector (GRPCLB. Defaultketamakey)) c, err: = Grpc. Dial ("", Grpc. Withinsecure (), Grpc. Withbalancer (b), Grpc. Withtimeout (time. Second)) if Err! = Nil { log. Printf ("Grpc Dial:%s", err) return } client: = Proto. Newtestclient (c) for I: = 0; I < 10; i++ { ctx: = context. Background () hashdata: = FMT. Sprintf ("aaaa%d", i) resp, err: = client. Say (context. Withvalue (CTX, GRPCLB. Defaultketamakey, Hashdata), &proto. Sayreq{content: "Ketama"}) if Err! = Nil { & nbsp; log. PRINTLN (Err) time. Sleep (time. Second) continue } log. Printf (resp. Content) time. Sleep (time. Second) }}
The code for the server is as follows, run the 3 service processes using the following command, and then start the client.
Go run Main.go-node node1-port 28544
Go run Main.go-node node2-port 18562
Go run Main.go-node node3-port 27772
Package Mainimport ( "flag" "FMT" etcd "Github.com/coreos/etcd /client " " Github.com/liyue201/grpc-lb/examples/proto " registry" github.com/ Liyue201/grpc-lb/registry/etcd " " Golang.org/x/net/context " " Google.golang.org/grpc " " log " " net " " Sync " "Time") var NodeID = flag. String ("Node", "Node1", "Node ID") var port = flag. Int ("Port", 8080, "listening port") type rpcserver struct { addr string s &NBSP ; *grpc. Server}func newrpcserver (addr string) *rpcserver { s: = Grpc. NewServer () rs: = &RpcServer{ addr:addr, s: s, } return rs}func (S *rpcserver) Run () {& nbsp; listener, err: = Net. Listen ("TCP ", s.addr) if Err! = Nil { log. Printf ("Failed to listen:%v", err) return } Log. Printf ("RPC listening on:%s", s.addr) proto. Registertestserver (S.S, s) s.s.serve (listener)}func (S *rpcserver) Stop () { S.s.gracefulstop ()}func (S *rpcserver) Say (CTX context. Context, req *proto. Sayreq) (*proto. SAYRESP, error) { text: = "Hello" + req. Content + ", I am" + *nodeid log. Println (text) return &proto. Sayresp{content:text}, Nil}func StartService () { etcdconfg: = Etcd. config{ endpoints: []string{"http://120.24.44.201:4001"}, } registry, Err: = registry. Newregistry ( registry. option{   Etcdconfig: etcdConfg, registrydir: "/grpc-lb", servicename: "Test", nodeid: *nodeID, ndata: Registry. nodedata{ addr:fmt. Sprintf ("127.0.0.1:%d", *port), // metadata:map[string]string{"Weight": "1"},//Configure weights here, do not configure default is 1 }, ttl:10 * time. second, }) if err! = Nil { Log. Panic (Err) return } server: = Newrpcserver ( Fmt. SprinTF ("0.0.0.0:%d", *port)) &NBSP;WG: = Sync. waitgroup{} &NBSP;WG. ADD (1) go func () { server. Run () &NBSP;WG. Done () } () &NBSP;WG. ADD (1) go func () { registry. Register () &NBSP;WG. Done ()  ,} () //stop the server after one minute //go func () { & nbsp // time. Sleep (time. Minute) // server. Stop () // registry. Deregister () //} () &NBSP;WG. Wait ()}//go run Main.go-node node1-port 28544//go run Main.go-node node2-port 18562//go run Main.go-node node3-port 27772func Main () { flag. Parse () startservice ()}
390 Reads