對(duì)于EOS,? 因?yàn)橛泻芨卟l(fā)需要,?才有了同步到MongoDB的想法, 所幸, EOS對(duì)MongoDB支持非常友好, 這確實(shí)比ETH強(qiáng).? 為了同步EOS, 前后一兩周,? 一路踩坑過(guò)來(lái), 真是不少問(wèn)題, 針對(duì)這些坑, 做一些總結(jié)
服務(wù)器選型, 多核心+SSD
EOS到MongoDB同步過(guò)程, 對(duì)硬盤IO和CPU要求都很高, 至少8核心CPU, 32G以上內(nèi)存, 本地SSD作為數(shù)據(jù)盤是比較合適的方案,?
可以先按量購(gòu)買進(jìn)行測(cè)試,瓶頸總是在IO, 然后是CPU, 然后又是IO, 不斷切換,直到找到穩(wěn)定的方法, 這樣會(huì)更省錢,
你也可以選擇SSD云盤, 或者M(jìn)ongoDB云服務(wù), 只要你錢多, 還不怕折騰, 事實(shí)上, IO能超過(guò)本地SSD硬盤陣列的很少見(jiàn)
另外, 使用中國(guó)境外的服務(wù)器, 省去很多因?yàn)閾?dān)心國(guó)家防火墻的問(wèn)題, 浪費(fèi)寶貴的時(shí)間
使用EOS離線包, EOS開始并不需要很高的帶寬, 5Mbps足以
當(dāng)前2018/11/14, EOS的數(shù)據(jù)在200G之內(nèi), MongoDB的數(shù)據(jù)在2T之內(nèi),
我們使用CentOS 7.x版本,?
設(shè)置好數(shù)據(jù)盤后, 可以創(chuàng)建好mongodb和eos的目錄做后續(xù)準(zhǔn)備
/mnt/mongo/log
/mnt/mongo/data
/mnt/eos
安裝和配置MongoDB
MongoDB不要使用EOS默認(rèn)安裝的3.6.3版本,? 測(cè)試中, 偶爾發(fā)現(xiàn)某些指令導(dǎo)致MongoDB服務(wù)停止,? 然后又得花上一天時(shí)間replay
可以在下面網(wǎng)站選擇最新的版本下載,?
https://www.mongodb.com/download-center/community
3.6.3版本的數(shù)據(jù)文件和最新版4.0是兼容的, 我們使用的是mongodb-linux-x86_64-rhel70-4.0.4.tgz
cd ~
wget? https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-4.0.4.tgz
tar xvzf?./mongodb-linux-x86_64-rhel70-4.0.4.tgz
配置mongod.conf到/etc/, 實(shí)際上任何目錄都可以
# mongod.conf
# for documentation of all options, see:
#? http://docs.mongodb.org/manual/reference/configuration-options/
# where to write logging data.
systemLog:
? destination: file
? logAppend: true
? path: /mnt/mongo/log/mongod.log
# Where and how to store data.
storage:
? dbPath: /mnt/mongo/data
? journal:
? ? enabled: true
#? engine:
#? mmapv1:
#? wiredTiger:
# how the process runs
processManagement:
? fork: true? # fork and run in background
? #ipidFilePath: /var/run/mongodb/mongod.pid? # location of pidfile
? timeZoneInfo: /usr/share/zoneinfo
# network interfaces
net:
? port: 27017
? bindIp: 127.0.0.1? # Enter 0.0.0.0,:: to bind to all IPv4 and IPv6 addresses or, alternatively, use the net.bindIpAll setting.
#security:
#? authorization: enabled
#operationProfiling:
#replication:
#sharding:
## Enterprise-Only Options
#auditLog:
#snmp:
注意,?配置中指定的目錄要放到數(shù)據(jù)盤上,?并且確保目錄都已經(jīng)成功建立
#試試啟動(dòng)MongoDB
/root/mongodb-linux-x86_64-rhel70-4.0.4/bin/mongod? ? -f? /etc/mongod.conf
#試試關(guān)閉MongoDB
pkill?mongod
然后, 你可以配置mongoDB的外網(wǎng)訪問(wèn)權(quán)限, 這是個(gè)可選項(xiàng)
為了安全, 一定要先配置mongoDB的用戶權(quán)限, 進(jìn)入mongo客戶端, 執(zhí)行下面指令, 最后的auth要是1表示成功
/root/mongodb-linux-x86_64-rhel70-4.0.4/bin/mongo
> db.createUser({user:'eos',pwd:'eosfku',roles:[{role:'readWrite',db:'EOS'}]})
>use EOS
>db.auth('eos','eosfku')
> 1
然后修改?/etc/mongod.conf, 打開下面選項(xiàng)
net:
? port: 27017
? bindIp: 0.0.0.0
security:
? authorization: enabled
關(guān)閉mongod, 啟動(dòng)mongod,
下載mongo客戶端, 例如Robo 3T試一試
編譯EOS, 不要浪費(fèi)時(shí)間去用Docker EOS
編譯之前, 先要解決mongo_db_plugin的一個(gè)問(wèn)題,? 原生的mongo_db_plugin只有一個(gè)線程入庫(kù), 這會(huì)形成瓶頸,? 我們稍作修改,? 保持原有邏輯, 改為多線程,并追加一個(gè)參數(shù)mongodb-thread-size來(lái)配置線程個(gè)數(shù), 修改的多線程版文件在此:
https://github.com/llxisdsh/mongo_db_plugin_mt/blob/master/mongo_db_plugin.cpp
EOS原版文件在此:
https://github.com/EOSIO/eos/blob/master/plugins/mongo_db_plugin/mongo_db_plugin.cpp
cd ~
git clone https://github.com/EOSIO/eos --recursive
#git clone https://github.com/EOS-Mainnet/eos -b mainnet-1.4.3? --recursive
#也可以指定最近的穩(wěn)定版本tag下載, 下載大概要幾分鐘
#下載完成后, 記得覆蓋修改過(guò)的mongo_db_plugin.cpp
cd eos
./eosio_build.sh
#這得經(jīng)過(guò)一個(gè)小時(shí), 你至少開始得坐在電腦前, 不斷確定Yes
./eosio_install.sh
#它會(huì)建立一些EOS程序軟連接到 /usr/local/bin.? 你可以把該目錄加入PATH
配置EOS
需要通過(guò)genesis.json初始化config.ini
cd ~
wget https://eosnodes.privex.io/static/genesis.json
或者使用下面文本建立genesis.json也可以:
{
"initial_timestamp": "2018-06-08T08:08:08.888",
"initial_key": "EOS7EarnUhcyYqmdnPon8rm7mBCTnBoot6o7fE2WzjvEX2TdggbL3",
"initial_configuration": {
"max_block_net_usage": 1048576,
"target_block_net_usage_pct": 1000,
"max_transaction_net_usage": 524288,
"base_per_transaction_net_usage": 12,
"net_usage_leeway": 500,
"context_free_discount_net_usage_num": 20,
"context_free_discount_net_usage_den": 100,
"max_block_cpu_usage": 200000,
"target_block_cpu_usage_pct": 1000,
"max_transaction_cpu_usage": 150000,
"min_transaction_cpu_usage": 100,
"max_transaction_lifetime": 3600,
"deferred_trx_expiration_window": 600,
"max_transaction_delay": 3888000,
"max_inline_action_size": 4096,
"max_inline_action_depth": 4,
"max_authority_depth": 6
}
}
然后, 通過(guò)下面方式生成初始的config.ini
cd ~
nodeos --genesis-json=genesis.json
CTRL+C
ll?.local/share/eosio/nodeos/config/config.ini
配置文件默認(rèn)生成到
.local/share/eosio/nodeos/config/config.ini
修個(gè)這個(gè)文件, 配置下面內(nèi)容:
abi-serializer-max-time-ms = 15000
chain-state-db-size-mb =? 4096
http-validate-host = false
#mongodb plugin 隊(duì)列到達(dá)這個(gè)尺寸時(shí)將sleep, 設(shè)置更大是沒(méi)有意義的
mongodb-queue-size = 4096
#這個(gè)參數(shù)是mongo_db_plugin多線程版指定的線程數(shù)量, 需要小于mongodb-uri 的maxPoolSize參數(shù), 如果是遠(yuǎn)程DB該參數(shù)要更大
mongodb-thread-size = 50
#mongoDB連接url,?maxPoolSize的參數(shù)是mongodb連接池的限制數(shù)量
mongodb-uri = mongodb://127.0.0.1:27017/EOS?maxPoolSize=100
#如果指定了用戶權(quán)限, 如下
#mongodb-uri = mongodb://eos:eosfku@127.0.0.1:27017/EOS?maxPoolSize=100
#EOS RPC 服務(wù), 可選
http-server-address = 0.0.0.0:8888
plugin = eosio::http_plugin?#必要
plugin = eosio::chain_plugin?#必要
plugin = eosio::mongo_db_plugin?#同步mongodb必要
plugin = eosio::chain_api_plugin #可選
plugin = eosio::history_api_plugin#可選
......
p2p-peer-address = mainnet.eoslaomao.com:443
......
配置這個(gè)文件很花時(shí)間,? 可是一旦配置OK, 你完全可以復(fù)制到其他服務(wù)器使用
關(guān)于p2p-peer-address, 可以使用下面的配置, 以及網(wǎng)上其他來(lái)源
正常同步
cd ~
#試試啟動(dòng)
nodeos -d /mnt/eos 2>&1 | tee ./eos.log &
#試試關(guān)閉
pkill nodeos
注意, 啟動(dòng)時(shí), 注意指定EOS的數(shù)據(jù)目錄, 后面的參數(shù)是為了同時(shí)把控制臺(tái)也寫入eos.log文件
這樣就方便任何時(shí)候使用下面指令跟蹤eos日志
tail -f?./eos.log
這種普通同步的方式, 可能需要幾周或幾個(gè)月同步完成~, 直到你必須考慮下面的辦法
下載EOS離線包, 會(huì)省去幾倍的時(shí)間
到上面網(wǎng)址中選擇最新的離線包, 復(fù)制地址
cd /mnt/eos
wget xxxx/blocks_2018-11-12-07-00.tar.gz
tar xvzf??blocks_2018-11-12-07-00.tar.gz
replay離線包然后同步
#replay離線包并同步, 并清空mongodb
nodeos -d /mnt/eos --hard-replay-blockchain --wasm-runtime wavm --mongodb-wipe? 2>&1 | tee ./eos.log &
#出現(xiàn)問(wèn)題中斷時(shí),?replay離線包并同步, 保留部分DB數(shù)據(jù), 從指定塊寫入
nodeos -d /mnt/eos --hard-replay-blockchain --wasm-runtime wavm?--mongodb-block-start 1234567? 2>&1 | tee ./eos.log &
--hard-replay-blockchain參數(shù)是盡量replay模式, 離線部分完成,會(huì)自動(dòng)跟上常規(guī)同步
--wasm-runtime wavm 參數(shù)是指定EOS虛擬機(jī)模式, 據(jù)說(shuō)這樣更快一點(diǎn),?
--mongodb-wipe 參數(shù)是清空mongodb, 需要配合--hard-replay-blockchain使用
--mongodb-block-start 參數(shù)是指跳過(guò)之前的塊, 從指定塊以后寫入
參數(shù)詳解參照:
https://developers.eos.io/eosio-nodeos/docs/
你可以通過(guò)下面指令觀察恢復(fù)狀態(tài), 或者通過(guò)查詢mongodb查看塊數(shù)
#追蹤nodeos日志
tail -f ./eos.log
#mongo查詢
db.runCommand({"find":"blocks", "sort":{"block_num": -1}, "limit":1, "projection":{"block_num":1, "block.timestamp":1, "block_id":1},})
即便這樣, 你仍然需要等待幾天或更長(zhǎng)時(shí)間, 這完全取決于服務(wù)器的CPU和IO能力
離線數(shù)據(jù)replay完成后, 完全可以更換到用普通云盤的服務(wù)器.
如果需要更換, 你可以使用scp在服務(wù)器之間復(fù)制, 記得用內(nèi)網(wǎng)IP呦
scp -r root@xxx.xxx.xxx.xxx:/mnt/eos/blocks /mnt/eos
事實(shí)上, 你應(yīng)該會(huì)用到3次以上;(======
中斷容易產(chǎn)生數(shù)據(jù)重復(fù)
在磕磕絆絆走到最后發(fā)現(xiàn),? 每次中斷, 使用--mongodb-block-start 指令之后,? 都有部分?jǐn)?shù)據(jù)是重復(fù)的, 因?yàn)榕聛G總會(huì)往小了寫,? 可悲的是mongodb插件竟然不建立唯一索引,? 所以就重復(fù)了. 原則上通過(guò)修改插件代碼是可行的, 留待需要人修改吧.?
解決超過(guò)2T硬盤的分區(qū)
fdisk不能超過(guò)2T的分區(qū), 如果很不幸, 你已經(jīng)scp了大量數(shù)據(jù)后才發(fā)現(xiàn), 原來(lái)磁盤只分配了2T,還有大量的扇區(qū)沒(méi)有被使用, 下面辦法可以數(shù)據(jù)無(wú)損擴(kuò)充分區(qū):
1. fdisk -l? 分區(qū)的記住起始的扇區(qū), 假設(shè)是2048
2. umount /dev/vdb1
3. fsck -f /dev/vdb1
4. parted /dev/vdb
(parted)? mklabel gpt
(parted)? unit s
(parted)? mkpart ...
(parted)? start 2048
(parted)? end -1
5. resize2fs /dev/vdb1
6. mount -a
雖然我很不看好EOS, 但是EOS的更新仍然日新月異,?本文預(yù)計(jì)很快就會(huì)失效, 希望有人借此提供EOS MongoDB 離線下載包
當(dāng)前EOS版本v1.4.3, mongodDB版本4.0.4