Table of Contents

  • 1. 前言
  • 2. 负载均衡
  • 3. 相关链接

1 前言

前面一篇文章分析了一个grpc call的大致调用流程,顺着源码走了一遍,但是grpc中有一些特性并没有进行分析,这篇blog主要就是分析负载均衡这个特性。负载均衡可以让你在使用grpc调用方法是连接不同的服务器。在启动的时候,grpc client会建立对所有服务器的连接,然后通过轮询算法拿不同的服务器。

2 负载均衡

负载均衡是在客户端实现的,通过在初始化一个grpc客户端传入一个负载均衡器,默认是通过轮询算法每次调用时切换调用的服务器,由于是在客户端做的,所以只能让服务器平摊压力,并不能实时的根据服务器的状态来进行负载均衡。比如某一刻所有的grpc客户端都轮到了同一个服务器(这里只是举例)。

//在clientconn.go的DialContext函数中
go func() {var addrs []Addressif cc.dopts.balancer == nil {// Connect to target directly if balancer is nil.//如果没有设置负载均衡器,则直接连接addrs = append(addrs, Address{Addr: target})} else {var credsClone credentials.TransportCredentialsif creds != nil {credsClone = creds.Clone()}config := BalancerConfig{DialCreds: credsClone,}//启动一个负载均衡器,start函数会启动一个watch监听地址的变化,而Notify返回一个通道,在每次服务器地址变化后的最新地址信息.if err := cc.dopts.balancer.Start(target, config); err != nil {waitC <- errreturn}ch := cc.dopts.balancer.Notify()if ch == nil {// There is no name resolver installed.addrs = append(addrs, Address{Addr: target})} else {addrs, ok = <-chif !ok || len(addrs) == 0 {waitC <- errNoAddrreturn}}}//对每一个地址进行连接, 因为这是客户端启动时,所以需要对所有地址操作.for _, a := range addrs {if err := cc.resetAddrConn(a, false, nil); err != nil {waitC <- errreturn}}close(waitC)
}()
..............
//省略一些代码
if ok {//这里开启一个监听goroutine,主要是监听服务器地址变化并对新的地址建立连接,对老的地址关闭连接go cc.lbWatcher()
}

上面的代码大致是说明了一个负载均衡器是怎么使用的,下面看看负载均衡具体的结构:

type Balancer interface {//启动一个负载均衡,内部会启动一个名称服务器的watcher,不断监听地址的变化Start(target string, config BalancerConfig) errorUp(addr Address) (down func(error))//得到下一次连接的地址Get(ctx context.Context, opts BalancerGetOptions) (addr Address, put func(), err error)//从服务器得到更新的地址,这个地址是更新后的所有地址Notify() <-chan []Address//关闭负载均衡器Close() error
}

负载均衡器有个默认实现在balancer.go中,使用的轮询算法。这个实现中包含了一个名字服务器的服务,我们可以通过实现一个名字服务器的接口,然后封装到这个负载均衡器中,这样就不需要自己实现整个负载均衡器。名字服务器的接口如下:

type Update struct {// Op indicates the operation of the update.Op Operation// Addr is the updated address. It is empty string if there is no address update.Addr string// Metadata is the updated metadata. It is nil if there is no metadata update.// Metadata is not required for a custom naming implementation.Metadata interface{}
}
// Resolver creates a Watcher for a target to track its resolution changes.
type Resolver interface {// Resolve creates a Watcher for target.//通过一个名字得到一个watcher,监听服务器地址变化。Resolve(target string) (Watcher, error)
}
// Watcher watches for the updates on the specified target.
type Watcher interface {// Next blocks until an update or error happens. It may return one or more// updates. The first call should get the full set of the results. It should// return an error if and only if Watcher cannot recover.// 得到下次更新的地址Next() ([]*Update, error)// Close closes the Watcher.Close()
}

负载均衡器的全貌大概就这些了,其中还有些细节我没有看到,目前来说我也不希望过早深入这些细节。所以负载均衡就到这里啦。

3 相关链接

  1. http://www.grpc.io/docs/guides/auth.html#overview 验证文档
https://guidao.github.io/grpc_balancer.html

GRPC golang版源码分析之客户端(二)相关推荐

  1. GRPC golang版源码分析之客户端(一)

    Table of Contents 1. 前言 2. 源码目录浏览 3. 客户端 4. 相关链接 1 前言 grpc是一个通用的rpc框架,用google实现,当然也有go语言的版本.在工作中主要用到 ...

  2. zookeeper源码分析之三客户端发送请求流程

    znode 可以被监控,包括这个目录节点中存储的数据的修改,子节点目录的变化等,一旦变化可以通知设置监控的客户端,这个功能是zookeeper对于应用最重要的特性,通过这个特性可以实现的功能包括配置的 ...

  3. idea 线程内存_Java线程池系列之-Java线程池底层源码分析系列(二)

    课程简介: 课程目标:通过本课程学习,深入理解Java线程池,提升自身技术能力与价值. 适用人群:具有Java多线程基础的人群,希望深入理解线程池底层原理的人群. 课程概述:多线程的异步执行方式,虽然 ...

  4. golang map源码分析

    2019独角兽企业重金招聘Python工程师标准>>> 1. map数据结构 Golang的map使用哈希表作为底层实现,一个哈希表里可以有多个哈希表节点,也即bucket,而每个b ...

  5. Spring Cloud源码分析——Ribbon客户端负载均衡

    年前聊了Eureka和Zookeeper的区别,然后微服务架构系列就鸽了三个多月,一直沉迷逛B站,无法自拔.最近公司复工,工作状态慢慢恢复(又是元气满满地划水).本文从以下3个方面进行分析(参考了翟永 ...

  6. Golang bytes源码分析

    bytes/bytes.go源码分析 Golang JDK 1.10.3 bytes包提供了操作[]byte的常用方法. 源码分析 func equalPortable(a, b []byte) bo ...

  7. 【转】ABP源码分析四十二:ZERO的身份认证

    ABP Zero模块通过自定义实现Asp.Net Identity完成身份认证功能, 对Asp.Net Identity做了较大幅度的扩展.同时重写了ABP核心模块中的permission功能,以实现 ...

  8. 【转】ABP源码分析三十二:ABP.SignalR

    Realtime Realtime是ABP底层模块提供的功能,用于管理在线用户.它是使用SignalR实现给在线用户发送通知的功能的前提 IOnlineClient/OnlineClient: 封装在 ...

  9. PDF阅读器系列之--MuPDF源码分析过程(二)

    博客找回来了,在那更新 http://blog.csdn.net/sky_pjf 前 时间好快,又一周过了,发现自己太忙了,博客都没去管-- 序 *MuPDF开源框架现在一直都在维护,我一般都会隔一周 ...

最新文章

  1. 阿里云发布新一代CDN 6.0 主打云与大数据融合
  2. 缓存应用--Memcached分布式缓存简介(二)
  3. VS调试启动编辑并继续功能
  4. 计算机水平考试改革,浅析全国计算机等级考试改革及应对策略
  5. 详解如何修改Laravel Auth使用salt和password来认证用户
  6. Installshield关于.NET安装时需要重启动的处理办法,以及延伸出的重启后继续安装的安装包的一点想法...
  7. 图的存储结构之邻接表(详解)
  8. Objective-C入门教程(摘录)
  9. stm8s + si4463 寄存器配置
  10. OpenCV—Python 导向滤波
  11. mysql analyze_MySQL数据库执行analyze采集信息
  12. 计算机专业口号 十六个字,霸气押韵16字班级口号(精选100句)
  13. 计算机专业教师技能比赛,青年教师展风采,技能比赛促提升
  14. Github+Jekyll —— 创建个人免费博客(四)jekyll第一个页面
  15. mysql dba高级教程_MySQL DBA高级视频教程 博瑞森一线DBA大神亲授
  16. Linux下开源pcb设计软件,KiCAD更好用的开源免费的原理图、PCB设计软件
  17. 华为社招机考考什么_牛客网-华为-2020届校园招聘上机考试-软件类机考-3
  18. 微信豆有什么作用?微信豆怎么用?附攻略
  19. SAP中输出质检Q状态库存清单处理实例
  20. RTTI (Runtime Type Identification)

热门文章

  1. djandgo model id
  2. JDK的动态代理深入解析(Proxy,InvocationHandler)(转)
  3. JAVA笔记(运算符)
  4. 第一部分:TCL基本知识
  5. linux系统-软链接与硬链接区别
  6. 一台服务器最多能创建多少个 TCP 连接?
  7. VNC与RDP的区别
  8. 实验技术杂志文献20180126
  9. 赋值运算符函数严谨性的几点思考
  10. Matlab神经网络十讲(8): 归一化、权重读取、(非)线性网络设计