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
使用示例:
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
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
}