Hyperledger Fabric(2) - 源码分析之Config 配置模块的设计

2024-05-07 13:32

本文主要是介绍Hyperledger Fabric(2) - 源码分析之Config 配置模块的设计,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. 背景

一个优秀的区块链开源性项目,配置参数的读取是必不可少的。通常来讲,项目会基于现有配置读取框架上进行开发。

本文主要从源码角度探索Fabric 的配置读取原理。

2.查找相关代码

从 Hyperledger Fabric(1) - 整体架构和源码结构 文章中可知/fabric/core目录是项目的核心代码区,所以从此处入手查找配置参数的读取模块是否在其中。

果不其然/fabric/core/config目录即是配置的代码,查看 /fabric/core/config/config.go 代码内容可发现Fabric 的配置系统主要运用第三方包 viper。

viper可以对系统环境变量、 yaml/json 等格式的配置文件甚至是远程配置进行读取和设置 ,并可以在不重启服务的情况下动态设置新的配 项的值并使之实时生效。是一个专门处理配置的解决方案,拥有眼镜蛇的称号,和命令行的库 cobra 出自同一个开发者 spfl3 之手。

3. 源码分析

3.1 读取配置文件主模块

/fabric/core/config/config.go 中代码量不多,主要看InitViper函数,具体查看以下中文注释

func InitViper(v *viper.Viper, configName string) error {var altPath = os.Getenv("FABRIC_CFG_PATH")// 首先判断环境变量 FABRIC_CFG_PATH 是否有值, 如果有值说明是用户人为定义FABRIC 配置文件的路径if altPath != "" {// If the user has overridden the path with an envvar, its the only path// we will consider//判断路径是否存在if !dirExists(altPath) {return fmt.Errorf("FABRIC_CFG_PATH %s does not exist", altPath)}//如果路径存在,将FABRIC_CFG_PATH 内容添加作为配置文件的路径AddConfigPath(v, altPath)/*若没有定义该环境变量的值 ,则用代码添加两个路径作为搜索配置文件的路径1.首先将当前路径作为搜索配置文件的路径2.如果OfficialPath = "/etc/hyperledger/fabric"存在,则使用此路径作为搜索配置文件的路径*/} else {// If we get here, we should use the default paths in priority order://// *) CWD// *) /etc/hyperledger/fabric// CWDAddConfigPath(v, "./")// And finally, the official pathif dirExists(OfficialPath) {AddConfigPath(v, OfficialPath)}}/*调用 SetConfigName()设置配置文件名,所指的的配置文件名 configName 是由参数传递进来的*/// Now set the configuration file.if v != nil {v.SetConfigName(configName)} else {viper.SetConfigName(configName)}return nil
}

另外需要注意的是 InitViper 第一个参数 *viper.Viper 。在InitViper 函数中,无论是添加搜索路径(使用的是 AddConfigPath 函数),还是设置要搜索的配置文件名( SetConfigName函数),都分为全局的 viper 和特定的 viper(也就是参数最终由viper.AddConfigPathviper. SetConfigName 完成是全局的; 由 v.AddConfigPathv.SetConfigName 完成则是特定的。

这样可以很方便地初始化需要单独使用 viper的模块 。如下篇文章将要分析的 orderer 模块,即是采用单独的viper来进行配置。

3.2 peer命令搜索路径和配置文件

/fabric/cmd从命令方式看,大概率是此项目主题或者工具的命令启动代码,从此入口可以找到/fabric/cmd/peer/main.go文件,代码如下,具体查看以下中文注释

// The main command describes the service and
// defaults to printing the help message.
var mainCmd = &cobra.Command{Use: "peer"}func main() {// For environment variables.//通过viper设置前缀为 common.CmdRoot = "core"环境变量前缀名viper.SetEnvPrefix(common.CmdRoot)//通过viper获取所有的环境变量,如果设置过了前缀则会自动补全前缀名viper.AutomaticEnv()replacer := strings.NewReplacer(".", "_")viper.SetEnvKeyReplacer(replacer)// Define command-line flags that are valid for all peer commands and// subcommands.mainFlags := mainCmd.PersistentFlags()mainFlags.String("logging-level", "", "Legacy logging level flag")viper.BindPFlag("logging_level", mainFlags.Lookup("logging-level"))mainFlags.MarkHidden("logging-level")cryptoProvider := factory.GetDefault()mainCmd.AddCommand(version.Cmd())mainCmd.AddCommand(node.Cmd())mainCmd.AddCommand(chaincode.Cmd(nil, cryptoProvider))mainCmd.AddCommand(channel.Cmd(nil))mainCmd.AddCommand(lifecycle.Cmd(cryptoProvider))// On failure Cobra prints the usage message and error string, so we only// need to exit with a non-0 statusif mainCmd.Execute() != nil {os.Exit(1)}
}
3.3 orderer命令如何搜索、读取配置文件

同样的,如果看/fabric/cmd/orderer/main.go文件,具体查看以下中文注释

// Main is the entry point of orderer process
func Main() {fullCmd := kingpin.MustParse(app.Parse(os.Args[1:]))// "version" commandif fullCmd == version.FullCommand() {fmt.Println(metadata.GetVersionInfo())return}//配置文件加载入口conf, err := localconfig.Load()if err != nil {logger.Error("failed to parse config: ", err)os.Exit(1)}initializeLogging()prettyPrintStruct(conf)

/fabric/orderer/common/loadconfig/config.go,具体查看以下中文注释

// Load parses the orderer YAML file and environment, producing
// a struct suitable for config use, returning error on failure.
func Load() (*TopLevel, error) {//新建独立的viperconfig := viper.New()//调用 InitViper函数,configName 为配置文件名`orderer`coreconfig.InitViper(config, "orderer")  //`coreconfig`包就是`/fabric/core/config`包//通过viper设置前缀为 Prefix = "ORDERER"环境变量前缀名config.SetEnvPrefix(Prefix)//通过viper获取所有的环境变量,如果设置过了前缀则会自动补全前缀名config.AutomaticEnv()replacer := strings.NewReplacer(".", "_")config.SetEnvKeyReplacer(replacer)//读取配置文件if err := config.ReadInConfig(); err != nil {return nil, fmt.Errorf("Error reading configuration: %s", err)}var uconf TopLevelif err := viperutil.EnhancedExactUnmarshal(config, &uconf); err != nil {return nil, fmt.Errorf("Error unmarshaling config into struct: %s", err)}uconf.completeInitialization(filepath.Dir(config.ConfigFileUsed()))return &uconf, nil
}

4. 继续从源码分析其它模块

请见下文
Hyperledger Fabric(3) - 源码分析之Peer启动流程

这篇关于Hyperledger Fabric(2) - 源码分析之Config 配置模块的设计的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/967485

相关文章

Python通用唯一标识符模块uuid使用案例详解

《Python通用唯一标识符模块uuid使用案例详解》Pythonuuid模块用于生成128位全局唯一标识符,支持UUID1-5版本,适用于分布式系统、数据库主键等场景,需注意隐私、碰撞概率及存储优... 目录简介核心功能1. UUID版本2. UUID属性3. 命名空间使用场景1. 生成唯一标识符2. 数

Java中读取YAML文件配置信息常见问题及解决方法

《Java中读取YAML文件配置信息常见问题及解决方法》:本文主要介绍Java中读取YAML文件配置信息常见问题及解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要... 目录1 使用Spring Boot的@ConfigurationProperties2. 使用@Valu

Android kotlin中 Channel 和 Flow 的区别和选择使用场景分析

《Androidkotlin中Channel和Flow的区别和选择使用场景分析》Kotlin协程中,Flow是冷数据流,按需触发,适合响应式数据处理;Channel是热数据流,持续发送,支持... 目录一、基本概念界定FlowChannel二、核心特性对比数据生产触发条件生产与消费的关系背压处理机制生命周期

Jenkins分布式集群配置方式

《Jenkins分布式集群配置方式》:本文主要介绍Jenkins分布式集群配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1.安装jenkins2.配置集群总结Jenkins是一个开源项目,它提供了一个容易使用的持续集成系统,并且提供了大量的plugin满

SpringBoot线程池配置使用示例详解

《SpringBoot线程池配置使用示例详解》SpringBoot集成@Async注解,支持线程池参数配置(核心数、队列容量、拒绝策略等)及生命周期管理,结合监控与任务装饰器,提升异步处理效率与系统... 目录一、核心特性二、添加依赖三、参数详解四、配置线程池五、应用实践代码说明拒绝策略(Rejected

SQL Server配置管理器无法打开的四种解决方法

《SQLServer配置管理器无法打开的四种解决方法》本文总结了SQLServer配置管理器无法打开的四种解决方法,文中通过图文示例介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录方法一:桌面图标进入方法二:运行窗口进入检查版本号对照表php方法三:查找文件路径方法四:检查 S

怎样通过分析GC日志来定位Java进程的内存问题

《怎样通过分析GC日志来定位Java进程的内存问题》:本文主要介绍怎样通过分析GC日志来定位Java进程的内存问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、GC 日志基础配置1. 启用详细 GC 日志2. 不同收集器的日志格式二、关键指标与分析维度1.

Python中re模块结合正则表达式的实际应用案例

《Python中re模块结合正则表达式的实际应用案例》Python中的re模块是用于处理正则表达式的强大工具,正则表达式是一种用来匹配字符串的模式,它可以在文本中搜索和匹配特定的字符串模式,这篇文章主... 目录前言re模块常用函数一、查看文本中是否包含 A 或 B 字符串二、替换多个关键词为统一格式三、提

Linux中SSH服务配置的全面指南

《Linux中SSH服务配置的全面指南》作为网络安全工程师,SSH(SecureShell)服务的安全配置是我们日常工作中不可忽视的重要环节,本文将从基础配置到高级安全加固,全面解析SSH服务的各项参... 目录概述基础配置详解端口与监听设置主机密钥配置认证机制强化禁用密码认证禁止root直接登录实现双因素

MySQL中的表连接原理分析

《MySQL中的表连接原理分析》:本文主要介绍MySQL中的表连接原理分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、环境3、表连接原理【1】驱动表和被驱动表【2】内连接【3】外连接【4编程】嵌套循环连接【5】join buffer4、总结1、背景