博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
golang grpc 负载均衡
阅读量:5936 次
发布时间:2019-06-19

本文共 2588 字,大约阅读时间需要 8 分钟。

微服务架构里面,每个服务都会有很多节点,如果流量分配不均匀,会造成资源的浪费,甚至将一些机器压垮,这个时候就需要负载均衡,最简单的一种策略就是轮询,顺序依次选择不同的节点访问。

grpc 在客户端提供了负载均衡的实现,并提供了服务地址解析和更新的接口(默认提供了 DNS 域名解析的支持),方便不同服务的集成

使用示例

conn, err := grpc.Dial(    "",    grpc.WithInsecure(),    // 负载均衡,使用 consul 作服务发现    grpc.WithBalancer(grpc.RoundRobin(grpclb.NewConsulResolver(        "127.0.0.1:8500", "grpc.health.v1.add",    ))),)

创建连接的时候可以使用 WithBalancer 选项来指定负载均衡策略,这里使用 RoundRobin 算法,其实就是轮询策略

与 consul 的集成

有了负载均衡策略,还需要一个地址解析和更新策略,可以使用 DNS 服务来实现,但如果我们使用 consul 来做服务的注册和发现,可以通过实现 ‘naming.Resolver’ 和 ‘naming.Watcher’ 接口来支持

  • naming.Resolver: 实现地址解析
  • naming.Watcher: 实现节点的变更,添加或者删除
func NewConsulResolver(address string, service string) naming.Resolver {    return &consulResolver{        address: address,        service: service,    }}type consulResolver struct {    address string    service string}func (r *consulResolver) Resolve(target string) (naming.Watcher, error) {    config := api.DefaultConfig()    config.Address = r.address    client, err := api.NewClient(config)    if err != nil {        return nil, err    }    return &consulWatcher{        client:  client,        service: r.service,        addrs:   map[string]struct{}{},    }, nil}type consulWatcher struct {    client    *api.Client    service   string    addrs     map[string]struct{}    lastIndex uint64}func (w *consulWatcher) Next() ([]*naming.Update, error) {    for {        services, metainfo, err := w.client.Health().Service(w.service, "", true, &api.QueryOptions{            WaitIndex: w.lastIndex, // 同步点,这个调用将一直阻塞,直到有新的更新        })        if err != nil {            logrus.Warn("error retrieving instances from Consul: %v", err)        }        w.lastIndex = metainfo.LastIndex        addrs := map[string]struct{}{}        for _, service := range services {            addrs[net.JoinHostPort(service.Service.Address, strconv.Itoa(service.Service.Port))] = struct{}{}        }        var updates []*naming.Update        for addr := range w.addrs {            if _, ok := addrs[addr]; !ok {                updates = append(updates, &naming.Update{Op: naming.Delete, Addr: addr})            }        }        for addr := range addrs {            if _, ok := w.addrs[addr]; !ok {                updates = append(updates, &naming.Update{Op: naming.Add, Addr: addr})            }        }        if len(updates) != 0 {            w.addrs = addrs            return updates, nil        }    }}func (w *consulWatcher) Close() {    // nothing to do}

参考链接

  • gRPC Name Resolution:
  • Load Balancing in gRPC:
  • dns_resolver:

代码地址:

thumb_up

转载请注明出处

本文链接:

转载于:https://blog.51cto.com/51reboot/2139937

你可能感兴趣的文章
MP4视频播放器代码
查看>>
Nginx 匹配 iphone Android 微信
查看>>
MFC_Combo_Box(组合框)控件的用法
查看>>
ldap
查看>>
我的友情链接
查看>>
CentOS 7更改网卡名称
查看>>
Yum软件仓库配置
查看>>
linux 压缩与解压总结
查看>>
mysql脚本1064 - You have an error in your SQL syntax; check the manual
查看>>
nessus 本地扫描(一)
查看>>
linux服务器磁盘陈列
查看>>
RHEL7/CentOS7 pxe+kickstart自动化系统安装
查看>>
交换机配置模式
查看>>
python----tcp/ip http
查看>>
我的友情链接
查看>>
第一本docker书学习笔记1-3章
查看>>
python中psutil模块使用相关笔记
查看>>
一個典型僵尸網絡淺析
查看>>
vmware克隆Centos6.4虚拟机网卡无法启动问题
查看>>
dba学习
查看>>