【ETCD】【源码解读】Etcd启动阶段配置解析跟踪

一、newConfig()

newConfig() 是 ETCD 启动过程中的一个重要函数,它用于初始化和配置 ETCD 的各种配置项。该函数构造了一个 config 类型的实例,并为其配置了多个启动参数、标志和默认值。接下来,我们将逐行解析该函数的具体实现。


1. 创建 config 实例

cfg := &config{ec:      *embed.NewConfig(),ignored: ignored,
}
  • cfg := &config{...}:创建一个新的 config 结构体实例,并为其各个字段赋予默认值。
  • ec: *embed.NewConfig():初始化 embed.Config,这是 ETCD 服务的配置,包含了网络监听、存储路径等基础配置。
  • ignored: ignoredignored 是一个包含需要忽略的标志名称的字符串切片。它用于存储那些不会被解析和使用的标志。

2. 初始化 configFlags 结构体

cfg.cf = configFlags{flagSet: flag.NewFlagSet("etcd", flag.ContinueOnError),clusterState: flags.NewSelectiveStringValue(embed.ClusterStateFlagNew,embed.ClusterStateFlagExisting,),fallback: flags.NewSelectiveStringValue(fallbackFlagExit,fallbackFlagProxy,),v2deprecation: flags.NewSelectiveStringsValue(string(cconfig.V2Depr1WriteOnly),string(cconfig.V2Depr1WriteOnlyDrop),string(cconfig.V2Depr2Gone)),
}
  • flagSet: flag.NewFlagSet("etcd", flag.ContinueOnError):创建一个新的 FlagSet 实例,该实例用于解析命令行参数。"etcd" 是标志集的名称,flag.ContinueOnError 表示在遇到错误时继续执行(不退出)。

  • clusterState: flags.NewSelectiveStringValue(...)clusterState 是一个标志,表示集群的状态。它使用 NewSelectiveStringValue 初始化,支持选择值 "new"(新集群)或 "existing"(已有集群)。这个标志告诉 ETCD 是启动一个新集群还是加入现有集群。

  • fallback: flags.NewSelectiveStringValue(...)fallback 是一个标志,控制发现失败时的处理方式。它的可选值为 "exit""proxy",决定在发现失败时退出或继续作为代理。

  • v2deprecation: flags.NewSelectiveStringsValue(...)v2deprecation 是一个包含多个选择值的标志,用于控制 ETCD v2 API 的弃用阶段。它使用 NewSelectiveStringsValue 初始化,支持不同的弃用阶段(如 "write-only""write-only-drop""gone")。


3. 定义 Usage 函数

fs := cfg.cf.flagSet
fs.Usage = func() {fmt.Fprintln(os.Stderr, usageline)
}
  • fs := cfg.cf.flagSet:获取 flagSet,该实例用于解析命令行标志。
  • fs.Usage = func():定义 Usage 函数,当用户输入 -h 或无效的标志时,Usage 会输出帮助信息。此处的 usageline 是预定义的帮助文本。

4. 添加标志和参数

cfg.ec.AddFlags(fs)
  • cfg.ec.AddFlags(fs):将 embed.Config 的标志添加到 flagSet 中。AddFlags 函数会将 ETCD 服务相关的配置项(如端口、数据目录等)添加到 flagSet,使得它们可以通过命令行传递。

5. 配置命令行标志

fs.StringVar(&cfg.configFile, "config-file", "", "Path to the server configuration file. Note that if a configuration file is provided, other command line flags and environment variables will be ignored.")
  • fs.StringVar(&cfg.configFile, "config-file", ""):添加 --config-file 标志,指定配置文件路径。该文件的内容会覆盖命令行参数和环境变量的设置。
fs.Var(cfg.cf.fallback, "discovery-fallback", fmt.Sprintf("Valid values include %q", cfg.cf.fallback.Valids()))
fs.Var(cfg.cf.clusterState, "initial-cluster-state", "Initial cluster state ('new' when bootstrapping a new cluster or 'existing' when adding new members to an existing cluster). After successful initialization (bootstrapping or adding), flag is ignored on restarts.")
fs.Var(cfg.cf.v2deprecation, "v2-deprecation", fmt.Sprintf("v2store deprecation stage: %q. ", cfg.cf.v2deprecation.Valids()))
  • fs.Var:为 fallbackclusterStatev2deprecation 配置标志。每个标志都绑定到 configFlags 结构体中的相应字段,并为用户提供合适的描述。
fs.BoolVar(&cfg.printVersion, "version", false, "Print the version and exit.")
  • fs.BoolVar(&cfg.printVersion, "version", false):添加 --version 标志,用于输出 ETCD 的版本信息并退出。

6. 处理 ignored 标志

for _, f := range cfg.ignored {fs.Var(&flags.IgnoredFlag{Name: f}, f, "")
}
  • for _, f := range cfg.ignored:遍历 ignored 字段(一个包含不需要处理的标志的切片),并为每个标志创建一个忽略的 flag

7. 返回配置实例

return cfg
  • return cfg:函数结束时返回配置实例 cfg。该实例包含了 ETCD 启动时的所有配置,包括命令行标志、配置文件、集群信息等。

二、parse()函数解析

parse 函数是 config 结构体的方法,负责解析传入的命令行参数,处理配置文件和环境变量,并根据解析结果返回相应的错误或配置。下面是该函数的详细逐行解析:


函数签名:

func (cfg *config) parse(arguments []string) error
  • cfg *config:接收一个指向 config 结构体的指针,parse 方法修改该配置实例。
  • arguments []string:命令行参数的切片,通常是 os.Args[1:]

1. 解析命令行参数:

perr := cfg.cf.flagSet.Parse(arguments)
  • cfg.cf.flagSet.Parse(arguments):解析传入的命令行参数 argumentsflagSet 是配置中的 FlagSet,负责命令行标志的解析。
  • 返回值 perr:解析过程中返回的错误,如果没有错误,perrnil

2. 错误处理:

switch {
case perr == nil:
case errors.Is(perr, flag.ErrHelp):fmt.Println(flagsline)os.Exit(0)
default:os.Exit(2)
}
  • perr == nil:如果解析成功,继续执行。
  • errors.Is(perr, flag.ErrHelp):如果错误是 flag.ErrHelp(用户请求帮助信息),则打印帮助文本 flagsline,并正常退出。
  • default:如果发生其他错误,程序退出并返回状态码 2。

3. 检查无效的标志:

if len(cfg.cf.flagSet.Args()) != 0 {return fmt.Errorf("%q is not a valid flag", cfg.cf.flagSet.Arg(0))
}
  • cfg.cf.flagSet.Args():获取所有未被解析的命令行参数。
  • 如果还有未解析的参数(即无效的标志),则返回一个错误,指明该标志无效。

4. 打印版本信息:

if cfg.printVersion {fmt.Printf("etcd Version: %s\n", version.Version)fmt.Printf("Git SHA: %s\n", version.GitSHA)fmt.Printf("Go Version: %s\n", runtime.Version())fmt.Printf("Go OS/Arch: %s/%s\n", runtime.GOOS, runtime.GOARCH)os.Exit(0)
}
  • cfg.printVersion:如果 --version 标志被设置为 true,则打印 ETCD 的版本信息、Git 哈希值、Go 版本以及操作系统架构信息。
  • os.Exit(0):打印完版本信息后正常退出程序。

5. 解析配置文件:

if cfg.configFile == "" {cfg.configFile = os.Getenv(flags.FlagToEnv("ETCD", "config-file"))
}
  • cfg.configFile:检查是否提供了配置文件路径(--config-file)。
  • 如果没有提供配置文件路径,则尝试从环境变量中获取 ETCD_CONFIG_FILE 值。

6. 从配置文件加载配置:

if cfg.configFile != "" {err = cfg.configFromFile(cfg.configFile)if lg := cfg.ec.GetLogger(); lg != nil {lg.Info("loaded server configuration, other configuration command line flags and environment variables will be ignored if provided",zap.String("path", cfg.configFile),)}
} else {err = cfg.configFromCmdLine()
}
  • cfg.configFile != "":如果指定了配置文件,调用 configFromFile 加载配置文件内容。
  • cfg.configFromFile(cfg.configFile):读取配置文件并应用到配置结构体。
  • 如果没有配置文件,使用命令行参数(configFromCmdLine)来加载配置。

7. 设置 ETCD v2 相关弃用配置:

if cfg.ec.V2Deprecation == "" {cfg.ec.V2Deprecation = cconfig.V2DeprDefault
}
  • cfg.ec.V2Deprecation:如果未设置 v2 API 弃用配置,设置为默认值 cconfig.V2DeprDefault

8. 解析 WarningUnaryRequestDuration 标志:

cfg.ec.WarningUnaryRequestDuration, perr = cfg.parseWarningUnaryRequestDuration()
if perr != nil {return perr
}
  • cfg.parseWarningUnaryRequestDuration():解析 --warning-unary-request-duration 标志,用于设置警告阈值。
  • 如果解析出错,返回错误。

9. 处理弃用的标志:

var warningsForDeprecatedFlags []string
cfg.cf.flagSet.Visit(func(f *flag.Flag) {if msg, ok := deprecatedFlags[f.Name]; ok {warningsForDeprecatedFlags = append(warningsForDeprecatedFlags, msg)}
})
if len(warningsForDeprecatedFlags) > 0 {if lg := cfg.ec.GetLogger(); lg != nil {for _, msg := range warningsForDeprecatedFlags {lg.Warn(msg)}}
}
  • cfg.cf.flagSet.Visit:遍历所有解析的标志,检查是否有弃用的标志。
  • deprecatedFlags:包含弃用标志的映射。
  • 日志警告:如果有弃用的标志,记录警告日志。

10. 返回配置解析错误:

return err
  • 如果过程中没有错误,返回 nil,表示解析成功。如果出现任何错误,将返回错误。

三、总结:

newConfig() 函数的主要作用是创建并初始化一个包含 ETCD 启动配置的实例。它负责:

  • 创建并配置命令行标志。
  • 加载和验证配置。
  • 提供 ETCD 启动时所需的所有配置信息。

该函数通过 flagSet 处理所有命令行标志,提供给 ETCD 启动过程所需的配置信息。

  • 命令行参数解析parse 方法主要负责解析命令行参数、配置文件和环境变量。
  • 版本信息输出:如果用户请求,打印 ETCD 的版本信息并退出。
  • 配置文件加载:支持从配置文件和命令行参数加载配置。
  • 弃用标志处理:检查是否使用了弃用的命令行标志,并记录警告。
  • 错误处理:在遇到无效标志或其他错误时,及时返回错误并中止。

该函数的目的是确保配置的正确性并处理所有启动时的参数设置。

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

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

相关文章

2.linux中调度kettle

一.准备转换,等会在linux中用 1.添加excel输入组件,并添加对应的文件 2.添加列拆分为多行组件 3.添加文本文件输出组件 4.保存转换 二.linux安装java 1.把jdk-8u144-linux-x64.tar.gz上传到linux的/lx目录下 2. 解压jdk包,然后配置环境变量…

第四节、电机定角度转动【51单片机-TB6600驱动器-步进电机教程】

摘要:本节介绍用电机转动角度计算步骤,从而控制步进电机转角 一、 计算过程 1.1 驱动器接收一个脉冲后,步进电机转动一步,根据驱动器设置的细分值 计算一个脉冲对应电机转动的角度step_x s t e p x s t e p X … … ① step_{x…

如何终身使用 100% 免费的服务器

作为开发人员,我们需要在云服务上运行和托管后端。有许多 BaaS(后端即服务)可用,但它们有一些限制。 如果我说我已经免费使用基于 Linux 的服务器超过 4-5 年了,那会怎样?是的,你没听错。我正在使用这台安装了 Ubuntu 20、24 GB RAM、4 个 CPU 和 200 GB 存储空间的 Lin…

【计算机组成原理】期末复习题库

5.主存储器和CPU之间增加cache的目的是 。 A.解决CPU和主存之间的速度匹配问题 B.扩大主存储器的容量 C.扩大CPU中通用寄存器的数量 D.既扩大主存容量又扩大CPU中通用寄存器的数量 在计算机系统中,CPU的速…

SAP中Smartforms 翻译越南语

点击打印预览 打印预览中确实是越南语 转出成PDF 成了乱码 SPAD中查询LP01其实是简体中文 换成LP02试试 显示看上去正常的 SPAD中的LP02 SU3可以设置自己的默认打印参数 查查Smartforms中的字体样式 是宋体,看上去不用为了越南文刻意改字体样式成TIMES 看这篇文章…

26.删除有序数组中的重复项 python

删除有序数组中的重复项 题目题目描述示例 1:示例 2:提示:题目链接 题解解题思路python实现代码解释提交结果 题目 题目描述 给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现…

R语言 | 峰峦图 / 山脊图

目的:为展示不同数据分布的差异。 1. ggplot2 实现 # 准备数据 datmtcars[, c("mpg", "cyl")] colnames(dat)c("value", "type") head(dat) # value type #Mazda RX4 21.0 6 #Mazda RX4 Wag …

四川创新志成健康管理有限公司

四川创新志成健康管理有限公司 成都市青羊区广富路168号 公司简介 四川创新志成健康管理有限公司成立于2021年,公司专注体外诊断领域,致力为医学实验室、生产厂家、 经销商提供专业的学术、技术增值服务,涵盖免疫、生化、输血等检测领域&a…

系统级 I/O

Unix I/O **了解 Unix I/O 将帮助你理解其他的系统概念。**I/O 是系统操作不可或缺的一部分。我们经常遇到 I/O 和其他系统概念之间的循环依赖。例如,I/O 在进程的创建和执行中扮演着关键的角色。反过来,进程创建又在不同进程间的文件共享中扮演着关键角…

Elasticsearch:使用阿里 infererence API 及 semantic text 进行向量搜索

在之前的文章 “Elasticsearch 开放推理 API 新增阿里云 AI 搜索支持”,它详细描述了如何使用 Elastic inference API 来针对阿里的密集向量模型,稀疏向量模型, 重新排名及 completion 进行展示。在那篇文章里,它使用了很多的英文…

基于公网的无线全双工内部通话系统在演出行业可以用吗?

文旅名城再出发,更待“烟花”绽繁花 2024年4月将开业的扬州首个大型沉浸式剧场-《运河密城》 以运河为原点 追随河的记忆 从春秋时代的吴王夫差 到贯通南北的大运河成形 穿梭时空 探索扬州的前世今生 「运河第一锹」古运河旁 有一处新地标正在悄然兴起 如…

POSTGRESQL跟ORACLE语法区别和相同之处

跟ORACLE语法区别之处 1. Update和delete语法区别 Pg 和MySQL Update和delete的时候表名不能加别名 2. 插入数字类型不一样 ORACLE 对number类型的数据可以用’’ 字符串标记插入,但是PG不行,必须要进行正确的数据类型 3. SEQ使用不同 ORACEL的SEQ…

C++编程物联网:舵机VS步进电机

舵机和步进电机都是常见的电机类型,它们在自动化和机器人控制中有着不同的应用场景。两者的主要区别在于控制方式、运动精度、适用范围等方面。下面详细介绍它们的作用、应用场景和主要区别。 1. 舵机(Servo Motor) 工作原理 舵机是一种具有反馈控制的电动机,通常由电动…

鸿翼参与撰写档案数据管理与长期保存策略基于数字中国战略的研究

​编者按:近日,由中国财富出版社有限公司出版的《档案数据管理与长期保存策略——基于数字中国战略的研究》正式发行,上海鸿翼软件技术股份有限公司董事长兼CEO龙凌云作为核心作者参与主要编写工作。 本书是在国家档案局立项科研项目“数字档…

机器学习中的图匹配问题—基础学习

机器学习中的图匹配问题 结合导师所给的方向,能否将实例之间的点匹配问题转换为点到实例之间的匹配问题来进行求解呢?这里结合师姐推荐的讲座首先对图匹配的这个方向来进行简单的了解和接触。 图匹配问题概述 图匹配就是:不仅考虑点之间的配…

2024.11.29——[HCTF 2018]WarmUp 1

拿到题&#xff0c;发现是一张图&#xff0c;查看源代码发现了被注释掉的提示 <!-- source.php--> step 1 在url传参看看这个文件&#xff0c;发现了这道题的源码 step 2 开始审计代码&#xff0c;分析关键函数 //mb_strpos($haystack,$needle,$offset,$encoding):int|…

gRPC 快速入门 — SpringBoot 实现(1)

目录 一、什么是 RPC 框架 &#xff1f; 二、什么是 gRPC 框架 &#xff1f; 三、传统 RPC 与 gRPC 对比 四、gRPC 的优势和适用场景 五、gRPC 在分布式系统中应用场景 六、什么是 Protocol Buffers&#xff08;ProtoBuf&#xff09;&#xff1f; 特点 使用场景 简单的…

工具篇--GitHub Desktop 使用

文章目录 前言一、GitHub Desktop 的使用&#xff1a;1.1 通过官网下载GitHub Desktop和安装&#xff1a;1.2 安装和使用&#xff1a;1.2.1 填充自己的标识&#xff1a;1.2.3 克隆项目&#xff1a;1.2.4 git 常用忽略项配置&#xff1a; 二、代码的更新和提交&#xff1a;2.1 代…

MySQL事物隔离级别详细解释

目录 事务隔离级别总结 实际情况演示 脏读(读未提交) 避免脏读(读已提交) 不可重复读 可重复读 幻读 解决幻读的方法 事务隔离级别总结 SQL 标准定义了四个隔离级别&#xff1a; READ-UNCOMMITTED(读取未提交) &#xff1a;最低的隔离级别&#xff0c;允许读取尚未提…

[每周一更]-(第126期):MQ解耦场景

消息队列&#xff08;MQ&#xff09;解耦是一种软件架构设计模式&#xff0c;主要通过中间件将系统中的生产者和消费者模块分离&#xff0c;减少模块之间的直接依赖&#xff0c;使系统具有更高的扩展性和灵活性。这种模式尤其适用于需要处理复杂业务逻辑、频繁请求或异步处理的…