goim中的 bilibili/discovery (eureka)基本概念及应用-程序员宅基地

技术标签: 运维  golang  大数据  

goim 文章系列(共5篇):

有个 slack 频道, 不少朋友在交流 goim , 欢迎加入slack #goim

0. 背景与动机

在学习 goim 过程中, bilibili/discovery 是一个服务注册/发现的依赖网元, golang 实现了 netflix/eureka 并作了一些扩展改进

这里顺带记录了对 bilibili/discovery 学习过程中的一些理解

1. discovery 在goim 中的角色与作用

上图标示了 bilibili/discoverygoim 中的位置, 与作用(以 comet / job 为例):

  • 部署一到多分 discovery 作为服务注册/发现网元 ( discovery 相互间会同步注册数据,细节见后)
  • comet 一到多个部署, 这里是一个 comet gRPC server 服务端
    • comet 启动果, 每一个部署向 discovery 进行--> 服务注册
    • 注册成功后与 discovery 之间保持一个健康状态同步( renew ), 见标示 1
    • comet 如果下线, discovery 会标示下线状态
  • job 一到多个部署, 这里是一个 comet gRPC client 客户端
    • job 启动后, 向 discovery 进行 polls 获取 goim-comet 所有服务实例列表--> 服务发现
    • job 持续监听 discovery 中的 goim-conet 服务节点列表, 同步到本地
    • job 向 goim-comet 实例( 整个列表) 分发 goim 消息 ---> job 的主体业务功能

如果 discovery 网元不存在, 那很简单, job 在配置文件中写死 comet 地址( 一到多个), job 的 comet-gRPC-client 直接向 comet 的 comet-gRPC-server 进行互通完成业务. 这样就失去了分布式的动态扩展能力


discovery 之间, 会同步注册的服务实例信息

注意 在 bilibili/discovery 中, discovery 本身被标记为

_appid = "infra.discovery"
复制代码

相互之间一样进行相互注册/更新, 同在相互之间同步 名为"infra.discovery" 与其他 app 的实例信息

在 discovery 的配置文件中, discovery 实例被称为 node , 由 nodes 参数进行配置, 配置定义如下

// Config discovery configures.
type Config struct {
	Nodes  []string  # ******************** 这是配置一到多个 discovery 实例的定义
	Region string
	Zone   string
	Env    string
	Host   string
}
复制代码

2. discovery / eureka 的基本概念

2.1 基本概念

discovery / eureka 中的基本概念, 如上图所示, 就是一个分区进行注册/调度的简单划分

  • Region 地区, 例如, 中国区, 南美区, 北美区...
  • Zone 可用区域, 例如中国区下的 gd 广东地区, sh 上海地区, 一般是指骨干 IDC 机房, 或者跨地区的逻辑区域, 这是同区内调度的主要划分点. 一般是同区内调度, 不会跨区调度
  • Env 再划分小一点的运行环境划分, 比如 Env = dev 开发环境, Env = trial 试商用...
  • appID 这是注册应用的名称, 服务注册与发现, 依赖的是 name ----> address 名称到地址的注册(写入/更新) 与发现( 获取名称对应的服务地址或服务地址列表)

: bilibili/discovery 是以 http 方式提供注册/更新/发现/同步...等服务注册与发现等业务功能

所以, 可以看到 discorevy 获取一个服务器节点, 是如下方式

curl 'http://127.0.0.1:7171/discovery/fetch?zone=gd&env=dev&appid=goim.comet&status=1'
复制代码

上面 URL 中, zone 对应就是获取 gd 广东区域内, 环境定义为 dev , appID 为 goim.comet 的服务器实例, 当然, status 是附加约束, 这里 status=1 表示过滤名称为 goim.comet 的服务器实例状态要求为 status = 1 ( 即接收服务请求的 goim.comet 实例列表)

上面的 curl 会返回以下结果

{
    "code": 0,
    "data": {
        "instances": {
            "gd": [
                {
                    "zone": "gd",                # *** ** 可用区域
                    "env": "dev",                # ****** 运行环境
                    "appid": "goim.comet",       # ****** appID 名称
                    "hostname": "hostname000000",
                    "version": "111",
                    "metadata": {
                        "provider": "",
                        "weight": "10"
                    },
                    "addrs": [
                        "http://172.1.1.1:8080",
                        "gorpc://172.1.1.1:8089" # ****** 有效的 gRPC 地址
                    ],
                    "status": 1,
                    "reg_timestamp": 1525948301833084700,
                    "up_timestamp": 1525948301833084700,
                    "renew_timestamp": 1525949202959821300,
                    "dirty_timestamp": 1525948301848680000,
                    "latest_timestamp": 1525948301833084700
                }
            ]
        },
        "latest_timestamp": 1525948301833084700
    }
}
复制代码

discovery/ eureka 换成 DNS 域名 可以在逻辑上表示为 schema://appID.Env.Zone.Region , 类似于 grpc://goim.comet.dev.gd.china.xxxxx.com

换成 etcd 可以表示为 /Region/Zone/Env/appID, 例如 "/china/gd/dev/goim.comet"

2.2 小结与配置建议

由上小节可知, bilibili/discovery 或 netflix/eureka 的配置中, 以下4个关键参数, 需要一一对应

  • region
  • zone
  • env 或 deployEnv
  • appID

在 goim 中, appID 已经在代码中标记为常量, 如下

# github.com/Terry-Mao/goim/cmd/comet/main.go

const (
	ver   = "2.0.0"
	appid = "goim.comet"
)

# github.com/Terry-Mao/goim/cmd/logic/main.go
const (
	ver   = "2.0.0"
	appid = "goim.logic"
)

复制代码

3. goim 中使用 bilibili/discovery

还是以 logic / comet 之间的 gRPC 为例

所有使用 bilibili/discovery 的配置是类似的, 在配置中, 包含以下定义

原始定义在 github.com/bilibili/di… 第 46行开始

// Config discovery configures.
type Config struct {
	Nodes  []string  # ******************** 这是配置一到多个 discovery 实例的定义
	Region string
	Zone   string
	Env    string
	Host   string
}
复制代码

在 comet 配置中定义为

在 comet 配置源文件中 github.com/Terry-Mao/g… 第 112 行

// Config is comet config.
type Config struct {
	Debug     bool
	Env       *Env            # ******************** 这里这里这里
	Discovery *naming.Config  # ******************** 这里这里这里
	TCP       *TCP
	Websocket *Websocket
	Protocol  *Protocol
	Bucket    *Bucket
	RPCClient *RPCClient
	RPCServer *RPCServer
	Whitelist *Whitelist
}
复制代码

在 job 配置源文件中 github.com/Terry-Mao/g… 第 59 行

// Config is job config.
type Config struct {
	Env       *Env            # ******************** 这里这里这里
	Kafka     *Kafka
	Discovery *naming.Config  # ******************** 这里这里这里
	Comet     *Comet
	Room      *Room
}
复制代码

就像第二节所说的, regoin / zone / env , 所以, 重点关注 Env / Discovery 两个配置定义, 重点在 Discovery 配置naming.Config 即可

3.1 在 comet 中的服务注册, 与服务更新

3.1.1 注册如下

源代码见 github.com/Terry-Mao/g… 第42/43 行

	// register discovery
	dis := naming.New(conf.Conf.Discovery)
	resolver.Register(dis)
	
复制代码
3.1.2 更新如下

该 comet 的注册信息更新代码放在一个 goroutine 中, 每10秒更新一次

源代码见 github.com/Terry-Mao/g… 第42/43 行

			if err = dis.Set(ins); err != nil {
				log.Errorf("dis.Set(%+v) error(%v)", ins, err)
				time.Sleep(time.Second)
				continue
			}
			time.Sleep(time.Second * 10)
复制代码

3.2 在 job 中的服务发现

3.2.1 job 中的注册代码, 实际是无用代码

在 job 代码中, 含有服务注册代码, 实际上是无用代码, 原因是, 只有服务端才需要进行服务注册, 而 job 实际上只有两个业务关联逻辑

  1. 对 kafka 进行消息订阅
  2. 向 tomet 中的 comet gRPC server 进行消息 push 推送

代码在 github.com/Terry-Mao/g… 第 28行

	// grpc register naming
	dis := naming.New(conf.Conf.Discovery)
	resolver.Register(dis)
复制代码
3.2.2 job 中的服务发现代码

代码在 github.com/Terry-Mao/g… 第 85行


func (j *Job) watchComet(c *naming.Config) {
	dis := naming.New(c)       # **************************** 构造符合 gRPC 要求的服务发现实例
	resolver := dis.Build("goim.comet")
	event := resolver.Watch()  # **************************** 监听 服务发现, 这里返回一个 channel
	select {                   # **************************** 从 channel 中循环获取返回
	case _, ok := <-event:
		if !ok {
			panic("watchComet init failed")
		}
		if ins, ok := resolver.Fetch(); ok {   # **************************** ins 即是返回的实例
			if err := j.newAddress(ins.Instances); err != nil {
				panic(err)
			}
			log.Infof("watchComet init newAddress:%+v", ins)
		}
	case <-time.After(10 * time.Second):
		log.Error("watchComet init instances timeout")
	}
	go func() {
		for {
			if _, ok := <-event; !ok {
				log.Info("watchComet exit")
				return
			}
			ins, ok := resolver.Fetch()     # **************************** ins 即是返回的实例
			if ok {
				if err := j.newAddress(ins.Instances); err != nil {
					log.Errorf("watchComet newAddress(%+v) error(%+v)", ins, err)
					continue
				}
				log.Infof("watchComet change newAddress:%+v", ins)
			}
		}
	}()
}
复制代码

4. bilibili/discovery 架构与实现简要解读

.............稍后一一道来, 哈, 先去挣点钱先.............

.

5. 一些必读的好文章

  1. 详解 Eureka 缓存机制 -- 文章作者: 冯永彪

.

欢迎交流与批评..... .

.

关于我

网名 tsingson (三明智, 江湖人称3爷)

原 ustarcom IPTV/OTT 事业部播控产品线技术架构湿/解决方案工程湿角色(8年), 自由职业者,

喜欢音乐(口琴,是第三/四/五届广东国际口琴嘉年华的主策划人之一), 摄影与越野,

喜欢 golang 语言 (商用项目中主要用 postgres + golang )

tsingson 写于中国深圳 小罗号口琴音乐中心, 2019/04/25

转载于:https://juejin.im/post/5cc10b086fb9a0323c526bb0

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_34293059/article/details/91432532

智能推荐

wince 德赛西威2413_德赛西威NAV230凯立德2016春季专版C2134-C7M07-3921J0S-程序员宅基地

文章浏览阅读772次。这是德赛西威NAV230凯立德2016春季专版C2134-C7M07-3921J0S,这款最新的专版为凯立德2016春季版,版本号:C2134-C7M07-3921J0S,分辨率为高清800*480,端口及分辨率为常用的COM2 9600。软件介绍德赛西威NAV230专用的凯立德导航地图又更新啦!凯粉们还在等什么。这款最新的专版为凯立德2016春季版,版本号:C2134-C7M07-3921J0S..._德赛西威地图下载

浅析virtio技术(2)virtio设备管理_virtio header-程序员宅基地

文章浏览阅读1.1k次。virtio协议定义了virtio通信遵循的接口,包含设备状态、设备支持的特性以及前后端数据传输的通道(virtqueue)。目前在使用的virtio规范有三个版本0.95、1.0和1.1。0.95版本是目前广泛在使用的版本,称为传统模式;1.0版本中协议将设备的配置部分做了一些调整,被称为现代模式;1.1版本则主要是新增了packedvirtqueue的支持。本文重点关注于virtio设备相关的规范定义。..._virtio header

研究:利用古代玉米基因组推断美国玉米群体演化历史(Science 2017)_parviglumis-程序员宅基地

文章浏览阅读1.7k次。Genomic estimation of complex traits reveals ancient maize adaptation to temperate North America,Kelly Swarts ,Rafal M. Gutaker,Detlef Weigel,Edward S. Buckler,Hernán A. Burbano,Science,4 Aug 2017 ,DOI: 10.1126/science.aam9425本文的特殊材料是 15 个古代玉米样本的基因组数据,._parviglumis

[渝粤教育] 天津城建大学 混凝土结构设计原理A 参考 资料_混凝土的抗压强度越高 其粘结强度越高-程序员宅基地

文章浏览阅读640次。教育-混凝土结构设计原理A-章节资料考试资料-天津城建大学【】第一章单元测验1、【单选题】混凝土结构设计方法的发展进程中,属于结构生命全过程设计法(即兼顾结构安全性、适用性和耐久性),且运用概率方法度量结构可靠性的是A、容许应力设计法B、破损阶段设计法C、基于概率理论的极限状态设计法D、极限状态设计法参考资料【 】2、【多选题】当构件的截面形状、截面尺寸以及混凝土强度级别均相同时,钢筋混凝土构件与素混凝土构件相比最显著的优势是A、抗裂度提高B、截面刚度提高C、承载力提高D、_混凝土的抗压强度越高 其粘结强度越高

【C++】忽略逗号或者自定义符号输入_c++ 定义函数不加逗号-程序员宅基地

文章浏览阅读4.3k次,点赞4次,收藏14次。例如,输入以逗号隔开的字符,忽略逗号1,2,3,4,,a,s,sdsd,schar*p; p = new char[100]; int i = 0; while (cin.get(p[i])) //逐个从流中读取字符到p中 { if (p[i] == ','|| p[i] == ' ') //忽略 空格和逗号 { continue; } else if (p[i] == '\n') //读取到空格时结束输入 { p[i] =NULL; break; _c++ 定义函数不加逗号

使用Web3.py构建、签署、发送以太坊交易_web3 python 发送eth-程序员宅基地

文章浏览阅读514次,点赞7次,收藏5次。无论是普通转账,还是智能合约的写入,都可以认为是一笔交易(Transaction)。在区块链世界,可导致区块链数据发生变化的数据,可简单理解为一笔“交易”。相反,send_raw_transaction处理的,反而是对以上文本数据进行签署后,生成的数据(二进制或16进制形式)。B. 构建build_transaction() + 签署sign_transaction + 发送send_raw_transaction()A. 使用transact(), 底层还是自动调用的send_transaction()_web3 python 发送eth

随便推点

webkit、blink、chromium、chrome关系_为什么新版的谷歌浏览器还是显示的webkit而不是blink-程序员宅基地

文章浏览阅读2k次。最近在browser/web开发中遇到的一些概念v8、mozjs、spidermonkeywebkit、gecko、trident、blinkchrominum、chrome、Safri、IE、Mozilla、Android Browser总结了它们之间的关系:Mozjs是SpiderMonley的具体实现方式。Chrome在Chromium上新增了一些Go..._为什么新版的谷歌浏览器还是显示的webkit而不是blink

springboot基础入门-程序员宅基地

文章浏览阅读399次。1.基础入门1、spring与springbootspringspring能做什么如下:微服务、响应式、云、web应用、无服务架构(类似java里的函数式编程)、批处理spring的生态具体请看链接https://spring.io/projects/spring-boot覆盖了:web开发、数据访问、安全控制、分布式、消息服务、移动开发、批处理spring5重大升级1.响应式编程左边响应式栈、右边Servlet栈2.内部源码设计更新基于Java8的一些新特性,spring也

使用python采集股票实时行情_python 全市场股票实时行情-程序员宅基地

文章浏览阅读79次。【代码】使用python采集股票实时行情。_python 全市场股票实时行情

卡顿分析:掉帧_layoutmanager 耗时卡顿-程序员宅基地

文章浏览阅读1.7k次,点赞2次,收藏2次。前言:Android中标准帧率是60FPS,每秒刷新60帧画面,那么每帧就要在大约16ms渲染完成,如果超过了16ms,就会仍然显示上一帧画面。对于用户来说就是界面被卡住了。尤其是在连续的滑动过程中,突然掉帧,对用户来说卡顿非常明显,体验很不好。反而如果刷新一直保持在一个稳定的帧率,对用户体验来说反而影响不大,比如王者荣耀的最高帧率也就30FPS,但是由于我们的眼睛对于24fps就已经感觉到流畅..._layoutmanager 耗时卡顿

Centos 7源码安装mariadb10.4.13_mariadb10.4 aarh-程序员宅基地

文章浏览阅读522次。一、环境[root@localhost mariadb-10.4.13]# ifconfig |grep 192.168 inet 192.168.1.107 netmask 255.255.255.0 broadcast 192.168.1.255[root@localhost mariadb-10.4.13]# cat /etc/redhat-release CentOS Linux release 7.7.1908 (Core)[root@localhost mariadb_mariadb10.4 aarh

MySQL5.7解压版卸载教程:停止服务、删除文件和注册表清除-程序员宅基地

文章浏览阅读434次。1. 卸载1.1 关闭服务管理员身份运行cmd,使用命令net stop mysql,停止服务。1.2 卸载服务使用命令mysqld -remove mysql卸载服务。1.3 删除文件将mysql安装的文件夹删除1.4 清除注册表信息运行Win+R,输入regedit,打开注册表。清除注册表中的MySql服务,有几个地方:HKEY_LOCAL_MACHINE\SYSTEM\ControlSet0..._mysql5.7压缩包卸载

推荐文章

热门文章

相关标签