作者:Derek
簡介
Github地址:https://github.com/Bytom/bytom
Gitee地址:https://gitee.com/BytomBlockc...
本章介紹bytom代碼Api-Server介面服務
作者使用MacOS作業系統,其他平台也大同小異
Golang Version: 1.8
Api-Server介面服務
Api Server是比原鏈中非常重要的一個功能,在比原鏈的架構中專門服務於bytomcli和dashboard,他的功能是接收並處理使用者和礦池相關的請求。預設啟動9888連接埠。總之主要功能如下:
- 接收並處理使用者或礦池發送的請求
- 管理交易:打包、簽名、提交等操作
- 管理本地比原錢包
- 管理本地p2p節點資訊
- 管理本地礦工挖礦操作等
在Api Server服務過程中,在監聽地址listener上接收bytomcli或dashboard的請求訪問。對每一個請求,Api Server均會建立一個新的goroutine來處理請求。首先Api Server讀取請求內容,解析請求,接著匹配相應的路由項,隨後調用路由項的Handler回呼函數來處理。最後Handler處理完請求之後給bytomcli響應該請求。
Api-Server源碼分析
在bytomd啟動過程中,bytomd使用golang標準庫http.NewServeMux()建立一個router路由器,提供請求的路由分發功能。建立Api Server主要有三部分組成:
- 初始化http.NewServeMux()得到mux
- 為mux.Handle添加多個有效router路由項。每一個路由項由HTTP要求方法(GET、POST、PUT、DELET)、URL和Handler回呼函數組成
- 將監聽地址作為參數,最終執行Serve(listener)開始服務於外部請求
建立Api對象
node/node.go
func (n *Node) initAndstartApiServer() { n.api = api.NewAPI(n.syncManager, n.wallet, n.txfeed, n.cpuMiner, n.miningPool, n.chain, n.config, n.accessTokens) listenAddr := env.String("LISTEN", n.config.ApiAddress) env.Parse() n.api.StartServer(*listenAddr)}
api/api.go
func NewAPI(sync *netsync.SyncManager, wallet *wallet.Wallet, txfeeds *txfeed.Tracker, cpuMiner *cpuminer.CPUMiner, miningPool *miningpool.MiningPool, chain *protocol.Chain, config *cfg.Config, token *accesstoken.CredentialStore) *API { api := &API{ sync: sync, wallet: wallet, chain: chain, accessTokens: token, txFeedTracker: txfeeds, cpuMiner: cpuMiner, miningPool: miningPool, } api.buildHandler() api.initServer(config) return api}
首先,執行個體化api對象。Api-server管理的事情很多,所以參數也相對較多。
listenAddr本地連接埠,如果系統沒有設定LISTEN變數則使用config.ApiAddress配置地址,預設為9888
NewAPI函數我們看到有三個操作:
- 執行個體化api對象
- api.buildHandler添加router路由項
- api.initServer執行個體化http.Server,配置auth驗證等
router路由項
func (a *API) buildHandler() { walletEnable := false m := http.NewServeMux() if a.wallet != nil { walletEnable = true m.Handle("/create-account", jsonHandler(a.createAccount)) m.Handle("/list-accounts", jsonHandler(a.listAccounts)) m.Handle("/delete-account", jsonHandler(a.deleteAccount)) // ... }}
router路由項過多。這裡只介紹關於帳號相關的handler。其他的handler大同小異。
m.Handle("/create-account", jsonHandler(a.createAccount))
我們可以看到一條router項由url和對應的handle回呼函數組成。當我們請求的url匹配到/create-account時,Api-Server會執行a.createAccount函數,並將使用者的傳參也帶過去。
啟動Api-Server服務
api/api.go
func (a *API) StartServer(address string) { log.WithField("api address:", address).Info("Rpc listen") listener, err := net.Listen("tcp", address) if err != nil { cmn.Exit(cmn.Fmt("Failed to register tcp port: %v", err)) } go func() { if err := a.server.Serve(listener); err != nil { log.WithField("error", errors.Wrap(err, "Serve")).Error("Rpc server") } }()}
通過golang標準庫net.listen方法,監聽本地的地址連接埠。由於http服務是一個持久啟動並執行服務,我們啟動一個go程專門運行http服務。當運行a.server.Serve沒有任何報錯時,我們可以看到伺服器上啟動的9888連接埠。此時Api-Server已經處於等待接收使用者的請求。