package main import ( "../clientImpl" "../constants" "fmt" "google.golang.org/grpc" "google.golang.org/grpc/balancer/roundrobin" "google.golang.org/grpc/resolver" "log" "time" ) // gRPC官方库负载均衡实现示例,客户端,参考 https://grpc-up-and-running.github.io/ func main() { // 以服务命名来建立与实际服务终结点的连接,默认仅连接第一个终结点 pickFirstConn, err := grpc.Dial( fmt.Sprintf("%s:///%s", constants.ExampleScheme, constants.ExampleServiceName), // "grpc:///go-example" 注意必须是三个斜杠 grpc.WithInsecure(), ) if err != nil { log.Fatalf("did not connect: %v", err) } defer func() { _ = pickFirstConn.Close() }() log.Println("==== Calling go-example with pick_first ====") clientImpl.MakeCalls(pickFirstConn, 10) // 以服务命名来建立与实际服务终结点的连接,设置以轮询策略连接 roundRobinConn, err := grpc.Dial( fmt.Sprintf("%s:///%s", constants.ExampleScheme, constants.ExampleServiceName), // "grpc:///go-example" 注意必须是三个斜杠 //grpc.WithBalancerName(roundrobin.Name), // 官方仅提供pick first和round robin两种策略,更多负载均衡策略找第三方或自己实现 // 因为WithBalancerName过时了,推荐用WithDefaultServiceConfig,其参数是个服务配置的JSON // 可配置的项目包括超时时间、最大请求响应大小等,参考 https://github.com/grpc/grpc/blob/master/doc/service_config.md grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"loadBalancingPolicy":"%s"}`, roundrobin.Name)), grpc.WithInsecure(), ) if err != nil { log.Fatalf("did not connect: %v", err) } defer func() { _ = roundRobinConn.Close() }() log.Println("==== Calling go-example with round_robin ====") clientImpl.MakeCalls(roundRobinConn, 10) // 停顿10秒再请求,此时可手工增减服务端启动的端口监听,以测试服务端部分节点掉线或新节点上线的情况 println(`sleeping ------------------------------------------------------->`) time.Sleep(10 * time.Second) clientImpl.MakeCalls(roundRobinConn, 10) } // 将resolver添加进resolvers map,必须在init函数中 // 服务命名和实际服务终结点列表的映射关系即在此时建立 // 此方案最不可行之处在于,在k8s这样的动态环境上,需要花费额外的成本和复杂度来维护这个映射 func init() { resolver.Register(&clientImpl.ExampleResolverBuilder{}) }