02.Fabric源码解析---peer命令结构(王雅震)
Fabric源碼解析2——peer命令結構
peer目錄結構
peer目錄結構自身十分清晰,一個main.go文件,其余文件夾除common,gossip外均為子命令集合,有chaincode,channel,clilogging,node,version五個,各司其職,供main.go整合使用。子命令文件夾中,與文件夾名稱相同的.go文件為主要源碼文件,其余的均為按功能劃分的動作命令源碼。
以node目錄為例,node自身作為根命令的一個子命令,在node.go中實現,而node這個命令自身又有start,status,stop這三個動作去執行不同的任務,分別在對應start.go,status.go,stop.go中實現。注意,start,status,stop其實也是子命令,是node這個子命令的子命令,因為他們是在命令層級中最終去干活的底層的人,我覺得用動作去形容他們更貼切一些。
chaincode channel clilogging common gossip node node.go start.go status.go stop.go version main.go第三方包
在Getting Started中,無論是在啟動peer容器時默認執行的命令,還是手工執行交易時在終端窗口所輸入的命令,都類有類似的格式,如peer channel…,peer node…,peer chaincode…,這種 命令+子命令+選項 的風格,讓人在感覺上毫無違和感。peer命令主要依賴第三方包github.com/spf13/cobra,由其組成基本的peer命令架構。所以在此簡單介紹一下cobra。
cobra既是一個用于生成命令行程序的庫,也是用來生成程序和命令文件的程序(即在命令行用cobra命令進行一系列操作,格式化生成一些使用cobra框架的源代碼文件,用戶可在此基礎上進行編程)。目前,peer源碼只將cobra當作一個庫進行使用。cobra基本用法如下:
創建一個(根)命令對象,其原型為Command,每個命令都是一個Command對象實例。創建命令對象其實就是填充Command中的成員的過程罷了。需要注意的是,Command中的成員還有很多,其中有一批字段名為*Run,*RunE形式的成員,其作用與Run類似,區別在于運行的時間有先有后,是否被子命令繼承,是否返回錯誤。
type Command struct { Use string //命令名稱字段,如你在命令行敲的是peer ...,則該字段值就是"peer"Short string //短說明字段Long string //詳細說明字段Run func(cmd *Command, args []string) //該命令所執行的函數... }RootCmd := &cobra.Command{...}如果有需要,對命令的添加flag,這一點可以簡單的理解為命令選項。
RootCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose output") RootCmd.Flags().StringVarP(&Source, "source", "s", "", "Source directory to read from")如果有需要,對根命令添加子命令,子命令與根命令本質是一樣的,只是人為的進行級別上的區分。
RootCmd.AddCommand(versionCmd)運行命令
RootCmd.Execute()
由于文章重點在peer,所以在此只做簡單介紹,更詳細的使用方法,可在godoc或github.com/spf13/cobra上學習。其實閱讀fabric源碼過程中有一個感覺,就是項目的大神們選用的第三方庫,一般都是既滿足需求,又比較容易學習和上手。
peer命令結構解析
我們現在正式從peer/main.go文件開始解析源碼,本文旨在解析peer的命令結構,因此只會涉及相關的源碼,其他部分將會在其他主題文章中對應分析。如果你對cobra的用法稍微熟悉后,很容易就可以看懂main函數的構建。peer目錄下的子命令的源碼結構非常類似,也基本逃不出上文介紹的關于cobra的基本操作。
首先定義了一個mainCmd命令,var mainCmd =&cobra.Command{…},該命令填充了Use,PersistentPreRunE和Run成員。Use如我們預見的那樣被賦值為peer,PersistentPreRunE先于Run執行,都被賦值了一個匿名函數。因為mainCmd只單純作為根命令,不實現由子命令實現的具體的交易事務,因此實現的只是PersistentPreRunE指定的檢查、初始化日志系統并緩存配置的功能,和Run指定的版本打印、命令幫助功能生成mainCmd對象的命令行標識對象mainFlags,mainFlags := mainCmd.PersistentFlags(),也就是peer命令的選項,并對該標識對像進行了維護,增加了version,logging_level兩個選項。這也對應了其在自身對象中設置PersistentPreRunE和Run的功能。
首先定義了一個mainCmd命令,var mainCmd =,mainCmd.AddCommand(…)。添加的命令有
1. version.Cmd() 2. node.Cmd() 3. chaincode.Cmd(nil) 4. clilogging.Cmd(nil) 5. channel.Cmd(nil)Cmd()是每個子命令文件中暴露出的函數,各自整合了各自的動作命令。
**啟動根命令,mainCmd.Execute()。**啟動了根命令,也就啟動了其下的所有命令。子命令結構解析,以node為例其實讀懂了peer命令,其余的子命令類推即可。在此還是啰嗦兩句吧。上文已經說了子命令的源碼結構是極其相似的,這里只以node為例。
**在node.go中,**首先定義了一個node命令對象,var nodeCmd = &cobra.Command{…}
**在Cmd函數中,**添加了startCmd(),statusCmd(),stopCmd()三個函數返回的start,status,stop子命令(動作命令),分別實現在start.go,status.go,stop.go。這三個命令的源碼結構也是基本一致,在此僅以start和start.go為例。
在start.go中,首先定義了一個start命令對象,var nodeStartCmd = &cobra.Command{…},其中對RunE成員賦值了一個匿名函數,函數體中執行了serve函數,這也是該命令最終會調用的函數。serve函數是一個非常重要,非常復雜的函數。記不記得在上篇介紹Fabric項目線頭的文章提到過的,在每個peer容器啟動后默認執行的就是peer node start –peer-defaultchain=false命令,在此處就對接上了,該命令最終調用執行的就是serve函數,同時也就是說,serve函數會做了很多很多的準備工作。
總結
以上是生活随笔為你收集整理的02.Fabric源码解析---peer命令结构(王雅震)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 网页title图标设置
- 下一篇: 网络爬虫js逆向解决网站登录RSA加密问