超级账本源码分析: peer命令结构

链块学院
企业专栏
热度: 16750

区块链应用技术开发,区块链开发,超级账本,本文介绍fabric peer命令的结构。

一、Peer命令解析

1.1 前言

Peer节点是Fabric中处理交易和存储区块的重要角色,peer命令提供了很多命令供用户使用,比如创建通道、加入通道、安装和调用链码等等。我们后面很多文章会通过分析某些命令的执行流程来理解Fabric各个模块,本小节首先分析peer命令的结构。

1.2 Peer命令结构

Peer命令有四个子命令分别是channel、chaincode、clilogging、node,从字面意思上很好理解,比如channel子命令负责通道相关的操作,chaincode负责链码相关的操作。这些子命令都会被main函数调用, 因为main函数是程序的入口。从官方的实例中我们可以看出,peer命令的输入都是类似的格式,比如 peer channel …、peer node …、peer chaincode…,这种命令的风格是“命令 + 子命令 + 选项”,下图是peer完整的命令结构:

peer命令


1.3 Peer命令解析

peer模块位置在fabric/peer,目录结构如下:


peer命令

目录结构很清晰,peer目录下只有一个main文件,peer的子命令都在peer的子目录下,比chaincode、channel、clilogging等。

peer命令使用的是第三方包github.com/spf13/cobra,cobra是一个用于生成命令行程序的库, cobra基本用法如下:

1.      创建一个根命令对象,类型为Command,每个命令都是一个Command对象实例。创建一个命令对象就是实现和填充Command中的成员。

type Command struct { 
    Use string    //命令的名称,比如在命令行敲peer version,这个字段就是“peer”
    Short string
    Long string
    Run func(cmd *Command, args []string)
    ...
}
RootCmd := &cobra.Command{...}


例如fabric的peer命令的定义如下:


var mainCmd = &cobra.Command{
Use: "peer",
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
     // check for CORE_LOGGING_LEVEL environment variable, which should override
     // all other log settings
     loggingSpec := viper.GetString("logging_level")
 
     if loggingSpec == "" {
         // if CORE_LOGGING_LEVEL not set, use the value for 'peer' from core.yaml
         loggingSpec = viper.GetString("logging.peer")
     }
     flogging.InitFromSpec(loggingSpec)
 
     return nil
},
Run: func(cmd *cobra.Command, args []string) {
     if versionFlag {
         fmt.Print(version.GetInfo())
     } else {
         cmd.HelpFunc()(cmd, args)
     }
},
}


2.      为命令添加flag,也就是添加命令行选项,比如下面这个就是peer的主命令添加了一个version选项,各个用法类似于go的flag包。

mainFlags := mainCmd.PersistentFlags()
mainFlags.BoolVarP(&versionFlag, "version", "v", false, "Display current version of fabric peer server")


3.      添加子命令

mainCmd.AddCommand(version.Cmd())
mainCmd.AddCommand(node.Cmd())
mainCmd.AddCommand(chaincode.Cmd(nil))
mainCmd.AddCommand(clilogging.Cmd(nil))
mainCmd.AddCommand(channel.Cmd(nil))


4.      执行命令

if mainCmd.Execute() != nil {
     os.Exit(1)
}

 

1.4 子命令解析

我们以node子命令为例来介绍:

1.在node.go中,首先定义了一个node命令对象,var nodeCmd = &cobra.Command{…}

// Cmd returns the cobra command for Node
func Cmd() *cobra.Command {
    nodeCmd.AddCommand(startCmd())
    nodeCmd.AddCommand(statusCmd())
    return nodeCmd
}
 
var nodeCmd = &cobra.Command{
    Use:   nodeFuncName,
    Short: fmt.Sprint(shortDes),
    Long:  fmt.Sprint(longDes),
}


2.在Cmd函数中,添加了start、stop、status三个子命令,子命令又分别在start.go,status.go,stop.go文件中实现。


3.在start.go中,首先定义了一个start命令对象,var nodeStartCmd = &cobra.Command{…},其中对RunE成员赋值了一个匿名函数,函数体中执行了serve函数,这也是该命令最终会调用的函数。如果我们在命令行中输入peer node start, 这个serve函数就会被调用,顾名思义serve会启动很多peer的服务。后面我们在分析serve函数具体细节。

 

1.5 总结

本章节主要介绍了fabric peer的命令处理方式,由于peer使用了cobra库,流程上跟cobra使用方法一致,下面一节我们会介绍peer node start命令的具体实现。


-END-

(未经授权,谢绝转载,版权最终解释权归链块学院所有)

声明:本文为入驻“火星财经 专栏”作者作品,不代表火星财经官方立场。
转载请联系网页底部:内容合作栏目,邮件进行授权。授权后转载时请注明出处、作者和本文链接。未经许可擅自转载本站文章,将追究相关法律责任,侵权必究。
提示:投资有风险,入市须谨慎,本资讯不作为投资理财建议。
本内容旨在传递行业动态,不构成投资建议或承诺。