bytom启动后怎么连接别的节点

免费建站   2024年05月10日 22:17  

本篇内容介绍了“bytom启动后怎么连接别的节点”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

比原启动后去哪里连接别的节点

最开始我对于这个问题一直有个疑惑:区块链是一个分布式的网络,那么一个节点启动后,它怎么知道去哪里找别的节点从而加入网络呢?

看到代码之后,我才明白,原来在代码中硬编码了一些种子地址,这样在启动的时候,可以先通过种子地址加入网络。虽然整个网络是分布式的,但是最开始还是需要一定的中心化。

预编码内容

对于配置文件config.toml,比原的代码中硬编码了配置文件内容:

config/toml.go#L22-L45

vardefaultConfigTmpl=`#ThisisaTOMLconfigfile.#Formoreinformation,seehttps://github.com/toml-lang/tomlfast_sync=truedb_backend="leveldb"api_addr="0.0.0.0:9888"`varmainNetConfigTmpl=`chain_id="mainnet"[p2p]laddr="tcp://0.0.0.0:46657"seeds="45.79.213.28:46657,198.74.61.131:46657,212.111.41.245:46657,47.100.214.154:46657,47.100.109.199:46657,47.100.105.165:46657"`vartestNetConfigTmpl=`chain_id="testnet"[p2p]laddr="tcp://0.0.0.0:46656"seeds="47.96.42.1:46656,172.104.224.219:46656,45.118.132.164:46656"`varsoloNetConfigTmpl=`chain_id="solonet"[p2p]laddr="tcp://0.0.0.0:46658"seeds=""`

可以看出,对于不同的chain_id,预设的种子是不同的。

当然,如果我们自己知道某些节点的地址,也可以在初始化生成config.toml后,手动修改该文件添加进去。

启动syncManager

那么,比原在代码中是使用这些种子地址并连接它们的呢?关键在于,连接的代码位于SyncManager中,所以我们要找到启动syncManager的地方。

首先,当我们使用bytomd node启动后,下面的函数将被调用:

cmd/bytomd/commands/run_node.go#L41

funcrunNode(cmd*cobra.Command,args[]string)error{//Create&startnoden:=node.NewNode(config)if_,err:=n.Start();err!=nil{//...}//...}

这里调用了n.Start,其中的Start方法,来自于Node所嵌入的cmn.BaseService:

node/node.go#L39

typeNodestruct{cmn.BaseService//...}

所以n.Start对应的是下面这个方法:

vendor/github.com/tendermint/tmlibs/common/service.go#L97

func(bs*BaseService)Start()(bool,error){//...err:=bs.impl.OnStart()//...}

在这里,由于bs.impl对应于Node,所以将继续调用Node.OnStart():

node/node.go#L169

func(n*Node)OnStart()error{//...n.syncManager.Start()//...}

可以看到,我们终于走到了调用了syncManager.Start()的地方。

syncManager中的处理

然后就是在syncManager内部的一些处理了。

它主要是除了从config.toml中取得种子节点外,还需要把以前连接过并保存在本地的AddressBook.json中的节点也拿出来连接,这样就算预设的种子节点失败了,也还是有可能连接上网络(部分解决了前面提到的中心化的担忧)。

syncManager.Start()对应于:

netsync/handle.go#L141

func(sm*SyncManager)Start(){gosm.netStart()//...}

其中sm.netStart(),对应于:

netsync/handle.go#L121

func(sm*SyncManager)netStart()error{//...//Ifseedsexist,addthemtotheaddressbookanddialoutifsm.config.P2P.Seeds!=""{//dialoutseeds:=strings.Split(sm.config.P2P.Seeds,",")iferr:=sm.DialSeeds(seeds);err!=nil{returnerr}}//...}

其中的sm.config.P2P.Seeds就对应于config.toml中的seeds。关于这两者是怎么对应起来的,会在后面文章中详解。

紧接着,再通过sm.DialSeeds(seeds)去连接这些seed,这个方法对应的代码位于:

netsync/handle.go#L229

func(sm*SyncManager)DialSeeds(seeds[]string)error{returnsm.sw.DialSeeds(sm.addrBook,seeds)}

其实是是调用了sm.sw.DialSeeds,而sm.sw是指Switch。这时可以看到,有一个叫addrBook的东西参与了进来,它保存了该结点之前成功连接过的节点地址,我们这里暂不多做讨论。

Switch.DialSeeds对应于:

p2p/switch.go#L311

func(sw*Switch)DialSeeds(addrBook*AddrBook,seeds[]string)error{//...perm:=rand.Perm(len(netAddrs))fori:=0;i<len(perm)/2;i++{j:=perm[i]sw.dialSeed(netAddrs[j])}//...}

这里引入了随机数,是为了将发起连接的顺序打乱,这样可以让每个种子都获得公平的连接机会。

sw.dialSeed(netAddrs[j])对应于:

p2p/switch.go#L342

func(sw*Switch)dialSeed(addr*NetAddress){peer,err:=sw.DialPeerWithAddress(addr,false)//...}

sw.DialPeerWithAddress(addr, false)又对应于:

p2p/switch.go#L351

func(sw*Switch)DialPeerWithAddress(addr*NetAddress,persistentbool)(*Peer,error){//...log.WithField("address",addr).Info("Dialingpeer")peer,err:=newOutboundPeerWithConfig(addr,sw.reactorsByCh,sw.chDescs,sw.StopPeerForError,sw.nodePrivKey,sw.peerConfig)//...}

其中的persistent参数如果是true的话,表明这个peer比较重要,在某些情况下如果断开连接后,还会尝试重连。如果persistent为false的,就没有这个待遇。

newOutboundPeerWithConfig对应于:

p2p/peer.go#L69

funcnewOutboundPeerWithConfig(addr*NetAddress,reactorsByChmap[byte]Reactor,chDescs[]*ChannelDescriptor,onPeerErrorfunc(*Peer,interface{}),ourNodePrivKeycrypto.PrivKeyEd25519,config*PeerConfig)(*Peer,error){conn,err:=dial(addr,config)//...}

继续dial,加入了超时:

p2p/peer.go#L284

funcdial(addr*NetAddress,config*PeerConfig)(net.Conn,error){conn,err:=addr.DialTimeout(config.DialTimeout*time.Second)iferr!=nil{returnnil,err}returnconn,nil}

addr.DialTimeout对应于:

p2p/netaddress.go#L141

func(na*NetAddress)DialTimeout(timeouttime.Duration)(net.Conn,error){conn,err:=net.DialTimeout("tcp",na.String(),timeout)iferr!=nil{returnnil,err}returnconn,nil}

“bytom启动后怎么连接别的节点”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

域名注册
购买VPS主机

您或许对下面这些文章有兴趣:                    本月吐槽辛苦排行榜

看贴要回贴有N种理由!看帖不回贴的后果你懂得的!


评论内容 (*必填):
(Ctrl + Enter提交)   

部落快速搜索栏

各类专题梳理

网站导航栏

X
返回顶部