## 1、加载命令行工具并解析命令行参数

orderer的命令行工具,基于gopkg.in/alecthomas/kingpin.v2实现,地址:http://gopkg.in/alecthomas/kingpin.v2。
相关代码如下

```go
var (
     //创建kingpin.Application
    app = kingpin.New( "orderer", "Hyperledger Fabric orderer node")
     //创建子命令start和version
    start = app.Command( "start", "Start the orderer node").Default()
    version = app.Command( "version", "Show version information")
)

kingpin.Version( "0.0.1")
//解析命令行参数
switch kingpin.MustParse(app.Parse(os.Args[ 1:])) {
case start.FullCommand():
     //orderer start的命令实现,下文展开讲解
case version.FullCommand():
     //输出版本信息
    fmt.Println(metadata.GetVersionInfo())
}
//代码在orderer/main.go
```

metadata.GetVersionInfo()代码如下:

```go
func GetVersionInfo() string {
    Version = common.Version //var Version string,全局变量
     if Version == "" {
        Version = "development build"
    }

     return fmt.Sprintf( "%s: \n Version: %s \n Go version: %s \n OS/Arch: %s",
        ProgramName, Version, runtime.Version(),
        fmt.Sprintf( "%s/%s", runtime.GOOS, runtime.GOARCH))
}
//代码在orderer/metadata/metadata.go
```

## 2、加载配置文件

配置文件的加载,基于viper实现,即https://github.com/spf13/viper。

```go
conf := config.Load()
//代码在orderer/main.go
```

conf := config.Load()代码如下:

```go
func Load() *TopLevel {
    config := viper.New()
     //cf.InitViper作用为加载配置文件路径及设置配置文件名称
    cf.InitViper(config, configName) //configName = strings.ToLower(Prefix),其中Prefix = "ORDERER"

    config.SetEnvPrefix(Prefix) //Prefix = "ORDERER"
    config.AutomaticEnv()
    replacer := strings.NewReplacer( ".", "_")
    config.SetEnvKeyReplacer(replacer)

    err := config.ReadInConfig() //加载配置文件内容

     var uconf TopLevel
     //将配置文件内容输出到结构体中
    err = viperutil.EnhancedExactUnmarshal(config, &uconf)
     //完成初始化,即检查空项,并赋默认值
    uconf.completeInitialization(filepath.Dir(config.ConfigFileUsed()))

     return &uconf
}

//代码在orderer/localconfig/config.go
```

TopLevel结构体及本地配置更详细内容,参考:[ Fabric 1.0源代码笔记 之 Orderer #localconfig(Orderer配置文件定义)]( localconfig.md)

## 3、初始化日志系统(日志输出、日志格式、日志级别、sarama日志)

```go
initializeLoggingLevel(conf)
//代码在orderer/main.go
```

initializeLoggingLevel(conf)代码如下:

```go
func initializeLoggingLevel(conf *config.TopLevel) {
     //初始化日志输出对象及输出格式
    flogging.InitBackend(flogging.SetFormat(conf.General.LogFormat), os.Stderr)
     //按初始化日志级别
    flogging.InitFromSpec(conf.General.LogLevel)
     if conf.Kafka.Verbose {
         //sarama为go语言版kafka客户端
        sarama.Logger = log.New(os.Stdout, "[sarama] ", log.Ldate|log.Lmicroseconds|log.Lshortfile)
    }
}
//代码在orderer/main.go
```

 

## 4、启动Go profiling服务(Go语言分析工具)

```go
initializeProfilingService(conf)
//代码在orderer/main.go
```

initializeProfilingService(conf)代码如下:

```go
func initializeProfilingService(conf *config.TopLevel) {
     if conf.General.Profile.Enabled { //是否启用Go profiling
         go func() {
             //Go profiling绑定的监听地址和端口
            logger.Info( "Starting Go pprof profiling service on:", conf.General.Profile.Address)
             //启动Go profiling服务
            logger.Panic( "Go pprof service failed:", http.ListenAndServe(conf.General.Profile.Address, nil))
        }()
    }
}
//代码在orderer/main.go
```

## 5、创建Grpc Server

```go
grpcServer := initializeGrpcServer(conf)
//代码在orderer/main.go
```

initializeGrpcServer(conf)代码如下:

```go
func initializeGrpcServer(conf *config.TopLevel) comm.GRPCServer {
     //按conf初始化安全服务器配置
    secureConfig := initializeSecureServerConfig(conf)
     //创建net.Listen
    lis, err := net.Listen( "tcp", fmt.Sprintf( "%s:%d", conf.General.ListenAddress, conf.General.ListenPort))
     //创建GRPC Server
    grpcServer, err := comm.NewGRPCServerFromListener(lis, secureConfig)
     return grpcServer
}
//代码在orderer/main.go
```

## 6、初始化本地MSP并获取签名

```go
initializeLocalMsp(conf)
signer := localmsp.NewSigner() //return &mspSigner{}
//代码在orderer/main.go
```

initializeLocalMsp(conf)代码如下:

```go
func initializeLocalMsp(conf *config.TopLevel) {
     //从指定目录加载本地MSP
    err := mspmgmt.LoadLocalMsp(conf.General.LocalMSPDir, conf.General.BCCSP, conf.General.LocalMSPID)
}
//代码在orderer/main.go
```

 

## 7、初始化MultiChain管理器(启动共识插件goroutine,接收和处理消息)

```go
manager := initializeMultiChainManager(conf, signer)
//代码在orderer/main.go
```

initializeMultiChainManager(conf, signer)代码如下:

```go
func initializeMultiChainManager(conf *config.TopLevel, signer crypto.LocalSigner) multichain.Manager {
    lf, _ := createLedgerFactory(conf) //创建LedgerFactory
     iflen(lf.ChainIDs()) == 0 { //链不存在
        initializeBootstrapChannel(conf, lf) //初始化引导通道(获取初始区块、创建链、添加初始区块)
    } else {
         //链已存在
    }

    consenters := make( map[ string]multichain.Consenter) //共识
    consenters[ "solo"] = solo.New()
    consenters[ "kafka"] = kafka.New(conf.Kafka.TLS, conf.Kafka.Retry, conf.Kafka.Version)
     return multichain.NewManagerImpl(lf, consenters, signer) //LedgerFactory、Consenter、签名
}
//代码在orderer/main.go
```

initializeBootstrapChannel(conf, lf)代码如下:

```go
func initializeBootstrapChannel(conf *config.TopLevel, lf ledger.Factory) {
     var genesisBlock *cb.Block
     switch conf.General.GenesisMethod { //初始区块的提供方式
     case"provisional": //根据GenesisProfile提供
        genesisBlock = provisional.New(genesisconfig.Load(conf.General.GenesisProfile)).GenesisBlock()
     case"file": //指定现成的初始区块文件
        genesisBlock = file.New(conf.General.GenesisFile).GenesisBlock()
     default:
        logger.Panic( "Unknown genesis method:", conf.General.GenesisMethod)
    }
    chainID, err := utils.GetChainIDFromBlock(genesisBlock) //获取ChainID
    gl, err := lf.GetOrCreate(chainID) //获取或创建chain
    err = gl.Append(genesisBlock) //追加初始区块
}
//代码在orderer/main.go
```

## 8、注册orderer service并启动grpcServer

```go
server := NewServer(manager, signer) //构造server
ab.RegisterAtomicBroadcastServer(grpcServer.Server(), server) //service注册到grpcServer
grpcServer.Start()
//代码在orderer/main.go
```

server := NewServer(manager, signer)代码如下:

```go
func NewServer(ml multichain.Manager, signer crypto.LocalSigner) ab.AtomicBroadcastServer {
    s := &server{
        dh: deliver.NewHandlerImpl(deliverSupport{Manager: ml}),
        bh: broadcast.NewHandlerImpl(broadcastSupport{
            Manager: ml,
            ConfigUpdateProcessor: configupdate.New(ml.SystemChannelID(), configUpdateSupport{Manager: ml}, signer),
        }),
    }
     return s
}
//代码在orderer/server.go
```





Fabric 1.0源代码分析(25) Orderer_区块链Fabric 1.0源代码分析(25) Orderer_区块链_02

网址:http://www.qukuailianxueyuan.io/

Fabric 1.0源代码分析(25) Orderer_区块链_03

Fabric 1.0源代码分析(25) Orderer_区块链_04

 

 



Fabric 1.0源代码分析(25) Orderer_区块链Fabric 1.0源代码分析(25) Orderer_区块链_02

网址:http://www.qukuailianxueyuan.io/

Fabric 1.0源代码分析(25) Orderer_区块链_03

Fabric 1.0源代码分析(25) Orderer_区块链_04