grpc的负载均衡
一.grpc的负载均衡介绍
1.官网地址
https://github.com/grpc/grpc/blob/master/doc/load-balancing.md
2.架构
3. Name Resolver(grpc从consul中同步服务信息进行负载均衡)
作用:从指定的DNS服务器或者一个注册中心拉取数据到本地来
目前已经有人已经做好此方面的功能,直接使用即可
官方文档介绍:https://github.com/mbobakov/grpc-consul-resolver
使用示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | package main import ( "time" "log" _ "github.com/mbobakov/grpc-consul-resolver" // It's important "google.golang.org/grpc" ) func main() { conn, err := grpc.Dial( "consul://127.0.0.1:8500/whoami?wait=14s&tag=manual" , grpc.WithInsecure(), grpc.WithDefaultServiceConfig(`{ "loadBalancingPolicy" : "round_robin" }`), ) if err != nil { log.Fatal(err) } defer conn.Close() ... } |
4.gin中集成
在initialize下的srv_conn.go初始化配置中配置如下即可 InitSrvConn
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | package initialize import ( "fmt" "github.com/hashicorp/consul/api" "go.uber.org/zap" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" "mxshop-api/user-web/global" "mxshop-api/user-web/proto" _ "github.com/mbobakov/grpc-consul-resolver" // It's important ) func InitSrvConn() { userConn, err := grpc.Dial( fmt.Sprintf( "consul://%s:%d/%s?wait=14s" , global.ServerConfig.ConsulInfo.Host, global.ServerConfig.ConsulInfo.Port, global.ServerConfig.UserSrvInfo.Name), //grpc.WithInsecure(), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithDefaultServiceConfig(`{ "loadBalancingPolicy" : "round_robin" }`), ) if err != nil { zap.S().Fatal( "【InitSrvConn】链接【用户失败】" ) } userSrvClient := proto.NewUserClient(userConn) global.UserSrvClient = userSrvClient } func InitSrvConn2() { //从注册中心获取到用户服务的信息 cfg := api.DefaultConfig() cfg.Address = "127.0.0.1:8500" //zap.S().Infof(fmt.Sprintf("配置:%s", global.ServerConfig.ConsulInfo.Host)) cfg.Address = fmt.Sprintf( "%s:%d" , global.ServerConfig.ConsulInfo.Host, global.ServerConfig.ConsulInfo.Port) userSrvHost := "" userSrvPost := 0 client, err := api.NewClient(cfg) if err != nil { panic(err) } data, err := client.Agent().ServicesWithFilter(fmt.Sprintf(`Service == "%s" `, global.ServerConfig.UserSrvInfo.Name)) //data, err := client.Agent().ServicesWithFilter(fmt.Sprintf("Service == \"%s\"", global.ServerConfig.UserSrvInfo.Name)) if err != nil { panic(err) } for _, value := range data { userSrvHost = value.Address userSrvPost = value.Port break } if userSrvHost == "" { zap.S().Fatal( "【InitSrvConn】链接【用户失败】" ) } //拨号连接用户RPC服务 userConn, err := grpc.Dial(fmt.Sprintf( "%s:%d" , userSrvHost, userSrvPost), grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { zap.S().Errorw( "[GetUserList]连接失败【用户服务失败】" , "msg" , err.Error()) } //1. 后续的用户服务下线了 2. 改端口了 3. 改ip了 负载均衡来做 //2. 已经事先创立好了连接,这样后续就不用进行再次tcp的三次握手 //3. 一个连接多个groutine共用,性能 - 连接池 userSrvClient := proto.NewUserClient(userConn) global.UserSrvClient = userSrvClient } |