本篇博客主要介绍一下在一台机器上建立多个节点,并且把节点连接在一起形成一个集群的方法笔记,以及配置时遇到的一些问题。
本文基于Ubuntu14.04 和 Geth 1.4.5-stable
建立一个私有节点时常用参数:
--nodiscover 使用这个参数,你的节点就不会被其他人发现,除非手动添加你的节点。否则,就只有一个被无意添加到一个陌生区块链上的可能,那就是跟你有相同的genesis文件和networkID。
--maxpeers 0 如果你不想有人连上你的测试链,就用maxpeers 0。或者,你可以调整参数,当你确切的知道有几个节点要连接上来的时候。
--rpc 允许RPC操作你的节点。这个参数在Geth上是默认的。
--rpcapi "db,eth,net,web3" 这个命令指示了允许通过RPC访问的命令。默认情况下,Geth允许web3。
--rpcport "8080"
--rpccorsdomain "http://chriseth.github.io/browser-solidity/"
--datadir "/home/etherTest" 私有链存放路径(最好跟公有链路径不同)
--port "30303" 网络监听端口,用来和其他节点手动连接
--identity “yooliee" 用来标识你的节点的,方便在一大群节点中识别出自己的节点
--networkid 1990 你自己的私有网络的id号
--rpccorsdomain "http://chriseth.github.io/browser-solidity/" 指定可以远程访问你的节点的URL, 值为"*"时是指任何地方都可以远程访问(避免使用*)
本地建立多个节点
为了能在本地建立多个节点,你必须确保:
为了建立一个本地集群,除了上面几个参数值不同以外,必须确保–networkid相同,即节点是属于同一个网络;创世区块相同、集群中的节点必须知道彼此。本测试建立三个节点,然后三个节点彼此相连,形成一个集群。
首先,建立一个文件夹,用来存放三个节点:
mkdir ether
所有节点的genesis.json文件必须相同:
{
"nonce": "0x0000000000000042",
"timestamp": "0x0",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "0x0",
"gasLimit": "0x80000000",
"difficulty": "0x1",
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0x3333333333333333333333333333333333333333",
"alloc": { }
}
建立第一个节点:
# 在ether目录下创建第一个目录,然后把上面的genesis.json文件复制到此目录下
$ cd ether
$ mkdir 01 && cd 01
# 用genesis.json生成创世区块
$ geth --datadir ~/ether/01 init genesis.json
# 此时01目录中生成了chaindata目录,里面就是存放区块链数据的地方
# 启动第一个节点
$ geth --identity "test" --rpc --rpccorsdomain "*" --datadir ~/ether/01 --port "30301" --nodiscover --rpcport 8101 --rpcapi "db,eth,net,web3" --networkid 1998 console 2>> ~/ether/01/geth.log
此时第一个节点启动成功了,可以通过eth.getBlock(0),查看创世区块信息,如下:
> eth.getBlock(0)
{
difficulty: 1,
extraData: "0x00",
gasLimit: 2147483648,
gasUsed: 0,
hash: "0x6099b65e564bd511f49e8f39ba27b6a68b6b78fd1481592257f06bbf93abe624",
logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
miner: "0x3333333333333333333333333333333333333333",
nonce: "0x0000000000000042",
number: 0,
parentHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
receiptRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
size: 505,
stateRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
timestamp: 0,
totalDifficulty: 1,
transactions: [],
transactionsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
uncles: []
}
通过admin.nodeInfo查看此节点的节点信息:
> admin.nodeInfo
{
enode: "enode://2f86dbb18242371fa0a8e7098cb13a012ad9d8ee80f0bbba94a798b16d3c6c3c247d3e333b8da27a591b38365f927a25359376d4bf38575bb0371a1365294f91@[::]:30301?discport=0",
id: "2f86dbb18242371fa0a8e7098cb13a012ad9d8ee80f0bbba94a798b16d3c6c3c247d3e333b8da27a591b38365f927a25359376d4bf38575bb0371a1365294f91",
ip: "::",
listenAddr: "[::]:30301",
name: "Geth/v1.4.5-stable-a269a713/linux/go1.4.2/test",
ports: {
discovery: 0,
listener: 30301
},
protocols: {
eth: {
difficulty: 13919423,
genesis: "0x6099b65e564bd511f49e8f39ba27b6a68b6b78fd1481592257f06bbf93abe624",
head: "0xdf1d69ee935ac6091eecf8a0f495f9dcdb644445feb265ea11f961ff9f5b45b5",
network: 1998
}
}
}
当连接同一个网络中的其他节点时,使用的就是上面的第一个字段enode的值,注意一下。
建立第二个节点
# 在ether目录下创建第二个目录,然后把上面的genesis.json文件复制到此目录下
$ cd ether
$ mkdir 02 && cd 02
# 用genesis.json生成创世区块
$ geth --datadir ~/ether/02 init genesis.json
# 此时02目录中生成了chaindata目录,里面就是存放区块链数据的地方
# 启动第二个节点
$ geth --identity "test" --rpc --rpccorsdomain "*" --datadir ~/ether/02 --port "30302" --nodiscover --rpcport 8102 --rpcapi "db,eth,net,web3" --networkid 1998 console 2>> ~/ether/02/geth.log
同样,第二个节点成功启动,可以通过eth.getBlock(0)查看区块信息:
> eth.getBlock(0)
{
difficulty: 1,
extraData: "0x00",
gasLimit: 2147483648,
gasUsed: 0,
hash: "0x6099b65e564bd511f49e8f39ba27b6a68b6b78fd1481592257f06bbf93abe624",
logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
miner: "0x3333333333333333333333333333333333333333",
nonce: "0x0000000000000042",
number: 0,
parentHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
receiptRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
size: 505,
stateRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
timestamp: 0,
totalDifficulty: 1,
transactions: [],
transactionsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
uncles: []
}
可以发现,02下的创世区块信息和01下的创世区块信息完全一样,因为是由同一个genesis.json生成,同一个网络中的创世区块也必须相同。
现在,已经创建好了两个节点,但是它们都还不知道彼此,两个节点是相对独立的存在。接下来,我们把两个节点连接起来:
# 在02节点的控制台里通过admin.addPeer(enodeUrlOfFirstInstance)添加第一个节点的信息,使节点1和节点2相连。
>admin.addPeer("enode://2f86dbb18242371fa0a8e7098cb13a012ad9d8ee80f0bbba94a798b16d3c6c3c247d3e333b8da27a591b38365f927a25359376d4bf38575bb0371a1365294f91@[::]:30301?discport=0")
> net.peerCount #检测有没有连接的节点
1
> admin.peers #查看连在02节点上的节点信息,可以看见id就是之前的01节点的id
[{
caps: ["eth/61", "eth/62", "eth/63"],
id: "2f86dbb18242371fa0a8e7098cb13a012ad9d8ee80f0bbba94a798b16d3c6c3c247d3e333b8da27a591b38365f927a25359376d4bf38575bb0371a1365294f91",
name: "Geth/v1.4.5-stable-a269a713/linux/go1.4.2/test",
network: {
localAddress: "[::1]:36114",
remoteAddress: "[::1]:30301"
},
protocols: {
eth: {
difficulty: 13919423,
head: "df1d69ee935ac6091eecf8a0f495f9dcdb644445feb265ea11f961ff9f5b45b5",
version: 63
}
}
}]
同理,创建第三个节点
# 在ether目录下创建第三个目录,然后把上面的genesis.json文件复制到此目录下
$ cd ether
$ mkdir 03 && cd 03
# 用genesis.json生成创世区块
$ geth --datadir ~/ether/03 init genesis.json
# 此时03目录中生成了chaindata目录,里面就是存放区块链数据的地方
# 启动第三个节点
$ geth --identity "test" --rpc --rpccorsdomain "*" --datadir ~/ether/03 --port "30303" --nodiscover --rpcport 8103 --rpcapi "db,eth,net,web3" --networkid 1998 console 2>> ~/ether/03/geth.log
然后在启动的控制台里面添加第一个节点:
> admin.addPeer("enode://2f86dbb18242371fa0a8e7098cb13a012ad9d8ee80f0bbba94a798b16d3c6c3c247d3e333b8da27a591b38365f927a25359376d4bf38575bb0371a1365294f91@[::]:30301?discport=0")
true
> net.peerCount
1
此时03节点添加了01节点,02节点添加了01节点,在01控制台中输入:
> net.peerCount
2
可以看见01节点现在有两个节点跟它相连。现在,三个节点相连,形成了一个小的集群,任意一个节点挖矿,挖到区块之后,都会同步到其他的两个节点。
以上是正确配置集群时用的方法,如果genesis.json文件不相同或者networkid不相同时,都不能添加成功。genesis.json不同,将会生成不一样的创世区块,networkid不同就是两个不同的网络,自然就不能添加成功。