dubbogo如何实现远程配置管理 -- 阅读官方文档

news2024/10/6 14:29:44

dubbo-go 中如何实现远程配置管理?

之前在 Apache/dubbo-go(以下简称 dubbo-go )社区中,有同学希望配置文件不仅可以放于本地,还可以放于配置管理中心里。那么,放在本地和配置管理中心究竟有哪些不一样呢?

放在本地,每次更新需要重启,配置文件管理困难,无法做到实时更新即刻生效。此外,本地文件还依赖人工版本控制,在微服务的场景下,大大的增加了运维的成本与难度。

而配置管理中心提供了统一的配置文件管理,支持文件更新、实时同步、统一版本控制、权限管理等功能。

配置中心

配置中心在 dubbo-go 中主要承担以下场景的职责:

  1. 作为外部化配置中心,即存储 dubbo.properties 配置文件,此时,key 值通常为文件名如 dubbo.properties , value 则为配置文件内容。
  2. 存储单个配置项,如各种开关项、常量值等。
  3. 存储服务治理规则,此时 key 通常按照 “服务名 + 规则类型” 的格式来组织,而 value 则为具体的治理规则。

就目前而言,dubbo-go 首要支持的是 Dubbo 中支持的开源配置中心,包括:

  1. Apollo:携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性,适用于微服务配置管理场景。
  2. ZooKeeper:一个分布式的,开放源码的分布式应用程序协调服务,是 Google 的 Chubby 一个开源的实现,是 Hadoop 和 Hbase 的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。
  3. Nacos: Alibaba 开源的配置管理组件,提供了一组简单易用的特性集,帮助您实现动态服务发现、服务配置管理、服务及流量管理。

而考虑到某些公司内部有自身的研发的配置中心,又或者当前流行而 Dubbo 尚未支持的配置中心,如 etcd,我们的核心在于设计一套机制,允许我们,也包括用户,可以通过扩展接口新的实现,来快速接入不同的配置中心。

那么在dubbo-go中究竟是怎么实现的呢?

我们的答案是:
基于动态的插件机制在启动时按需加载配置中心的不同实现。

dubbo-go设计

原逻辑为:启动时读取本地配置文件,将其加载进内存,通过配置文件中的配置读取注册中心的信息获取服务提供者,注册服务消费者。

有些读者会有点困惑,不是说好了使用配置中心的,为什么现在又要读取本地配置呢?答案就是,读取的这部分信息分成两部分:

  • 使用什么作为配置中心;
  • 该配置中心的元数据,比如说使用 zookeeper 作为配置中心,那么 zookeeper 的链接信息就是元数据,毕竟我们只有在知道了链接信息之后才能连上 zookeeper;

在改造的时候,需要考虑以下的问题:

  1. 如何实现支持多个配置中心?如何实现按需加载?

    通过抽象 DynamicConfiguration 让开发者可以快速支持多个配置中心。使用者导入指定的组件包后,在启动阶段将需要的组件加载进内存中,以便给程序按需调用,如下图绿色部分。

  2. 配置中心的配置加载阶段在什么时候?

    应在读取配置文件阶段后,读取并解析本地配置文件中配置中心信息。初始化配置中心链接,读取 /dubbo/config/dubbo/dubbo.properties 与 /dubbo/config/dubbo/应用名/dubbo.properties ,并将其加载到内存之中覆盖原有配置,监听其变更,实时更新至内存,如下图蓝色部分: img

ConfigCenterFactory

使用者加载对应配置中心模块后,在初始化阶段加入各配置中心模块往其中注册其初始化类。

var configCenterFactories = make(map[string]func() config_center.DynamicConfigurationFactory)

// SetConfigCenterFactory sets the DynamicConfigurationFactory with @name
func SetConfigCenterFactory(name string, v func() config_center.DynamicConfigurationFactory) {
	configCenterFactories[name] = v
}

// GetConfigCenterFactory finds the DynamicConfigurationFactory with @name
func GetConfigCenterFactory(name string) (config_center.DynamicConfigurationFactory, error) {
	if configCenterFactories[name] == nil {
		return nil, errors.New("config center for " + name + " is not existing, make sure you have import the package.")
	}
	return configCenterFactories[name](), nil
}

DynamicConfigurationFactory

整个动态配置中心的关键点就在DynamicConfigurationFactory上,其中通过解析内部自定义的URL,获取其协议类型,反射其参数,用于创建配置中心的链接。

// DynamicConfigurationFactory gets the DynamicConfiguration
type DynamicConfigurationFactory interface {
   GetDynamicConfiguration(*common.URL) (DynamicConfiguration, error)
}

如:

配置文件中配置:

config_center:
  protocol: zookeeper
  address: 127.0.0.1:2181
  namespace: test

dubbo-go 内部会解析为:

zookeeper://127.0.0.1:2181?namespace=test

在内部传递,用于初始化配置中心链接。

DynamicConfiguration

该接口规定了各个配置中心需要实现的功能:

  • 配置数据反序列化方式:目前只有Properties转换器,参见:DefaultConfigurationParser。
  • 增加监听器:用于增加监听数据变化后增加特定逻辑(受限于配置中心client端实现)
  • 删除监听器:删除已有监听器(受限于配置中心client端实现,目前所知nacos client没有提供该方法)
  • 获取路由配置:获取路由表配置
  • 获取应用及配置:获取应用及配置,如:协议类型配置等
// DynamicConfiguration for modify listener and get properties file
type DynamicConfiguration interface {
	Parser() parser.ConfigurationParser
	SetParser(parser.ConfigurationParser)
	AddListener(string, ConfigurationListener, ...Option)
	RemoveListener(string, ConfigurationListener, ...Option)
	// GetProperties get properties file
	GetProperties(string, ...Option) (string, error)

	// GetRule get Router rule properties file
	GetRule(string, ...Option) (string, error)

	// GetInternalProperty get value by key in Default properties file(dubbo.properties)
	GetInternalProperty(string, ...Option) (string, error)

	// PublishConfig will publish the config with the (key, group, value) pair
	PublishConfig(string, string, string) error

	// RemoveConfig will remove the config white the (key, group) pair
	RemoveConfig(string, string) error

	// GetConfigKeysByGroup will return all keys with the group
	GetConfigKeysByGroup(group string) (*gxset.HashSet, error)
}

img

优先考虑与现有 Dubbo 设计兼容,从而降低使用者的学习成本,dubbo-admin 作为服务提供者实现应用级配置管理, dubbo-go 作为消费端实现配置下发管理功能。下面以 ZooKeeper 为例,对服务提供者与服务消费者进行整体流程分析。

如何存储配置管理

dubbo-admin 配置管理中增加 global 配置,ZooKeeper 中会自动生成其对应配置节点,内容均为 dubbo-admin 中设置的配置。

  1. /dubbo/config/dubbo/dubbo.properties 对应全局配置文件。
  2. /dubbo/config/dubbo/ 应用名 /dubbo.properties 对应指定应用配置文件。
节点路径

img

上图展示了 dubbo.properties 文件在 ZooKeeper 和 Apollo 中的存储结构:

实现配置管理中心支持

以Apollo为例子,简单的介绍,如何实现一个新的配置管理中心。

选择配置管理中心Client/SDK

本例中使用的 Apollo Go Client 为:https://github.com/apolloconfig/agollo

节点路径

因为每隔配置管理中心的存储结构各有各的特点,导致dubbo在使用外部配置管理中心时,存储配置节点的结构不一样。在dubbo-configcenter找到希望支持的配置管理中心,而本例中Appollo则在ApolloDyncmicConfiguration.java。

注释中表明,Apollo namespace = governance (governance .properties) 用于治理规则,namespace = dubbo (dubbo.properties) 用于配置文件。

新建创建客户端方法,最好由客户端保持为单例。

func newApolloConfiguration(url *common.URL) (*apolloConfiguration, error) {
	c := &apolloConfiguration{
		url: url,
	}
	configAddr := c.getAddressWithProtocolPrefix(url)
	configCluster := url.GetParam(constant.CONFIG_CLUSTER_KEY, "")

	appId := url.GetParam(constant.CONFIG_APP_ID_KEY, "")
	namespaces := getProperties(url.GetParam(constant.CONFIG_NAMESPACE_KEY, cc.DEFAULT_GROUP))
	c.appConf = &config.AppConfig{
		AppID:         appId,
		Cluster:       configCluster,
		NamespaceName: namespaces,
		IP:            configAddr,
	}

	agollo.InitCustomConfig(func() (*config.AppConfig, error) {
		return c.appConf, nil
	})

	return c, agollo.Start()
}

以下为必须实现的方法,以下方法用于获取配置中心配置。

  • GetInternalProperty:在配置文件(Apollo 为 namespace)中,根据 key 获取对应 value;
  • GetRule:获取治理配置文件(Apollo 为 namespace);
  • GetProperties:获取整个配置文件(Apollo 为 namespace);

可选择实现的方法,如不实现,则不能动态更新 dubbo-go 中配置信息。

  • RemoveListener
  • AddListener

而 Parser & SetParser 使用默认实现即可,默认为 Properties 转换器。

使用方法

img

很显然,使用配置中心并不复杂,只需要把对应的依赖引入进来。在包初始化的时候,会创建出来对应的配置中心的实现。比如说加载 ZooKeeper 或者 Apollo 作为配置中心:

当然仅仅加载还不够,比如说虽然我加载了 zookeeper,但是我还需要知道怎么连上这个配置中心,即前面提到的配置中心的元数据,这部分信息是需要在本地配置出来的。比如说:

ZooKeeper

config_center:
  protocol: "zookeeper"
  address: "127.0.0.1:2181"

Apollo

config_center:
  protocol: "apollo"
  address: "127.0.0.1:8070"
  app_id: test_app
  cluster: dev

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/463975.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android 各大厂面试题汇总与详解(持续更新)

介绍 目前网络中出现了好多各种面试题的汇总,有真实的也有虚假的,所以今年我将会汇总各大公司面试比较常见的问题,逐一进行解答。会一直集成,也会收集大家提供的面试题,如有错误,请大家指出,经过…

原生小程序如何使用pdf.js实现查看pdf,以及关键词检索高亮

1.下载pdf.js库文件 前往 pdf.js 的 官网 下载库文件,下哪个版本都可以,后者适用于旧版浏览器,所以我下载的是后者 下载完成后,因为微信小程序打包的限制,我将库文件放到项目的后台系统了,在h5端处理会比在…

2023年淮阴工学院五年一贯制专转本数字电子技术考试大纲

2023年淮阴工学院五年一贯制专转本数字电子技术考试大纲 一、考核对象 本课程的考核对象是五年一贯制高职专转本电子科学与技术专业普通在校生考生。 二、考试目的及总体要求 通过本课程的考试,检查学生对掌握数字电路的基础理论知识的掌握程度,是否…

5大值得推荐的客户协作平台

提起在线文档平台,我们应该都会想到最常用的金山文档,石墨文档等,但是它们也只是实现了文档的在线多人协作,并没有形成完整系统的企业知识体系,文档协作的最高境界是要实现像书一样沉淀团队知识,像水一样促…

React | React脚手架解析

✨ 个人主页:CoderHing 🖥️ React.js专栏:React脚手架解析 🙋‍♂️ 个人简介:一个不甘平庸的平凡人🍬 💫 系列专栏:吊打面试官系列 16天学会Vue 11天学会React Node专栏 &#…

接口自动化测试数据处理:技术人员必备的一项技能

目录 前言: 1.定义测试数据结构 2.从文件中加载测试数据 3.使用faker库生成随机测试数据 4.在测试用例中使用测试数据 总结: 前言: 在进行接口自动化测试时,测试数据的准备和处理是至关重要的一环。测试数据的准确性和完整性…

heic格式转化jpg的3种好用方法

如果你是使用iOS手机的用户,那么一定对HEIC格式不陌生。虽然HEIC格式可以保存原始图像质量,但它只能在苹果手机或Mac电脑上打开。如果我们想要在安卓或Windows系统上打开,就需要使用转换软件将HEIC格式转换成常用的JPG格式。HEIC 是一种新型的…

设计模式总览 —— 导论

什么是 GOF 对接口编程而不是对实现编程。优先使用对象组合而不是继承。 设计模式的基石 封装继承多态顺序判断循环 设计模式总览 创建型模式(Creational Patterns) 单例(Singleton)模式原型(Prototype&#xff09…

mysql免安装版本(简化版)

1:解压mysql-5.7.26-winx64 2:添加data文件夹 3:添加my.ini文件 内容如下: port "3306" # 设置mysql的安装目录 basedir "D://tools\mysql-5.7.26-winx64\mysql-5.7.26-winx64\" # 设置mysql数据库的数…

推荐几个可以免费使用的ChatGPT工具

在ChatGPT相关API推出之后,各种工具如雨后春笋一般层出不穷,这篇文章就列举一些日常使用到的工具。 工具列表 OpenAI 在线读取任意网页内容包括视频(YouTube),并根据这些内容回答你提出的相关问题或总结相关内容支持…

RabbitMq-接收消息+redis消费者重复接收

在接触RammitMQ时,好多文章都说在配置中设置属性 # rabbitmq 配置 rabbitmq:host: xxx.xxx.xxx.xxxport: xxxxusername: xxxpassword: xxxxxx## 生产端配置# 开启发布确认,就是confirm模式. 消费端ack应答后,才将消息从队列中删除#确认消息已发送到队列(Queue)pub…

算法记录lday3 LinkedList 链表移除 + 链表构建 + 链表反转reverse

今日任务 ● 链表理论基础 ● 203.移除链表元素 ● 707.设计链表 ● 206.反转链表 链表理论基础 建议:了解一下链接基础,以及链表和数组的区别 文章链接:https://programmercarl.com/%E9%93%BE%E8%A1%A8%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A…

【SpringBoot源码剥析】| 依赖管理

目录 一. 🦁 依赖管理Ⅰ. 部分dependency导入时为啥不需要指定版本?1.1 父依赖启动器的工作1.2 问题答案 Ⅱ. 项目运行依赖的JAR包是从何而来的?2.1 分析源码2.2 问题答案 二. 🦁 总结 一. 🦁 依赖管理 Ⅰ. 部分dependency导入时…

Linux——中断和时间管理(中)

目录 驱动中的中断处理 中断下半部 软中断 tasklet 工作队列 驱动中的中断处理 通过上一节的分析不难发现,要在驱动中支持中断,则需要构造一个 struct irqaction的结构对象,并根据IRQ 号加入到对应的链表中(因为 irq_des 已经在内核初始…

golang微服务项目通用流水线

golang微服务项目通用流水线 工作中随着业务越来越大,微服务的项目也越来越多,最开始的时候是一个服务一个流水线,然后还分了三个环境,也就是一个服务三个流水线,后面就越来越不利于管理维护了,因此&#…

马云的创业故事及他人生中的摆渡人-创建阿里巴巴(五)

著名的“18罗汉大会” 以及“马云成功背后的男人” 1999年大年初五,杭州湖畔花园小区,18个人坐满了一屋子, 这是阿里巴巴的第一次全员大会,马云激情澎湃地讲了2个小时,并且专门请了摄影师全程录像。 这就是传说中的…

SD卡无法识别怎么办?

SD卡是一种可移动存储设备,广泛应用于各种电子设备,如Android智能手机、平板电脑或相机等,您可以将SD卡连接到计算机以传输一些文件。但有些时候,当您打开文件资源管理器后,可能会发现您的SD卡不显示,无法使…

即时通讯IM源码应该如何做好安全防护?

即时通讯(Instant Messaging,IM)在现代社会中已经成为了人们日常生活中必不可少的沟通工具。无论是在家庭、教育、商业或政府等各行各业中,IM都扮演着重要的角色。然而,随着IM使用率的增加,相应的安全威胁也…

程序员基础的硬件知识(cpu、主板、显卡、内存条等)

一、综合简介 cpu:负责运算数据,就等于你的大脑运算速度。 显卡:本来没有显卡,后来因为大家对图片要求越来越高,视频要求越来越高,啥都让cpu算太累了,于是分出来一个,专门用来计算…

华为云服务EulerOS release 2.0 版本安装大象数据库

1连接华为服务器 下载并按照命令yum install -y postgresql-server 2 初始化 postgresql-setup initdb 3启动 systemctl start postgresql.service 启动服务 4开放端口(如果防火墙已经关闭则可以省略) iptables -I INPUT -p tcp --dport 5432 -j ACCEPT 5验证安装结果&…