☰
FISCO BCOS节点扩容实操:原有机构内新增节点的完整指南
2026/10/17 5:51:10 网站建设 项目流程

前段时间有个项目到了验证阶段,原本链上是一个机构跑两个节点,业务方突然提出要提高交易吞吐能力,顺带多一层高可用保障,于是需要在原有机构内新增一个节点。这个操作看似只是多启一个进程,实际上涉及证书签发、群组配置、节点准入三个环节。任何一个环节弄错,新节点都有可能进程起来了、日志也刷了,却一直没有同步高度,甚至被群组直接忽略。

FISCO BCOS里,节点和群组是两回事。节点负责网络通信、交易处理和区块参与,群组是逻辑上的账本集合。你完全可以在同一个机构内跑很多节点,每个节点可以加入不同群组,只要它有对应群组的配置文件和同步能力。所以“原有机构内新增节点”核心就三件事:把证书链走通、把配置文件和端口弄对、把节点准入到群组里。

这篇主要面向2.0版本、使用build_chain.sh部署的联盟链。3.0的证书体系和命令有差异,但整体思路是相通的。我把这次实操和以前踩过的坑一起整理出来,给后面要做节点扩容的人做个参考。

1. 整体思路拆解:为什么“新增”比“初始化”更有讲究

1.1 节点扩容的真实场景价值

先聊为什么要在原有机构内新增节点,而不是新建一条链或者引入新机构。

最直接的动机是性能横向扩展。一个节点在交易量上来之后,容易出现写盘延迟、区块广播拥塞、CPU持续飙高。多一个节点,可以让网络和计算压力分摊开,业务高峰期不会卡在单点上。

其次是高可用。联盟链虽然有多个机构参与,但单个机构内部如果只有一个节点,这个节点挂了,机构就没法参与共识,业务可能直接中断。在原有机构内再跑一个节点,至少能顶住单点故障。之前有个项目,机构A的节点所在机器半夜宕机,结果那几小时里所有跟A相关的交易全部排队,后来他们加了第二节点做灾备,情况才彻底好转。

还有一种场景是安全隔离。原有节点要和别的业务共用主机,没办法动它,新增节点放到独立机器上,单独管理、单独加固,权限边界更干净。

和“新增机构”相比,原有机构内新增节点有一个本质区别:证书体系。FISCO BCOS的信任体系是CA到机构到节点三级签发。新增机构需要由CA给新机构签发agency证书,而原有机构新增节点,只需要该机构自己的agency证书和私钥来签发一个新节点证书。也就是说,不需要动CA,不需要重新生成机构根,只需在机构内部补发一份节点身份。所以,保留着当初生成机构的证书目录,操作会非常顺手;如果机构私钥弄丢了,那才是真的麻烦,后面我会专门说。

1.2 新增节点对整个链的影响面

对链的影响,取决于新节点以什么身份加入。

如果先以观察节点(observer)身份加入,几乎不影响现有共识和出块节奏,它只是默默同步区块数据。如果直接加为共识节点(sealer),群组出块节点数量会变化,共识消息传播模式跟着变,出块间隔、提案确认耗时会重新分布。

所以我的建议一直是:先以观察节点身份加入,同步追上最新高度后,再转为共识节点。这个顺序能显著降低操作风险。

另外,节点多了,P2P层的网络连接数也会增加。机器上的文件句柄数、带宽都要提前确认。之前见过一个项目,节点加完后发现带宽被打满,整个群组的出块间隔从500毫秒被拖到2秒,最后只能再调小网络限制。扩容之前先做一轮资源评估,非常必要。

2. 动手前准备:把现有节点目录和证书关系摸清

2.1 现有节点目录结构到底长什么样

一般用build_chain.sh搭出来的目录结构大致是这样:

nodes/ ├── 127.0.0.1 │ ├── node0 │ │ ├── config.ini │ │ ├── config.json │ │ ├── conf/ │ │ │ ├── ca.crt │ │ │ ├── cert.cnf │ │ │ ├── node.crt │ │ │ └── node.key │ │ ├── data/ │ │ │ ├── group.1.genesis │ │ │ └── group.1.ini │ │ ├── log/ │ │ ├── start.sh │ │ └── stop.sh │ └── node1 ├── cert/ │ ├── ca.crt │ ├── ca.key │ ├── agencyA/ │ │ ├── agency.crt │ │ ├── agency.key │ │ └── cert.cnf │ └── ... └── ...

如果这个目录还在,后面操作会舒服很多。注意cert目录不一定在nodes目录下,用脚本安装时也可能单独放在其他路径。查找方式很简单,直接看start.sh内容,或者全盘找agency.crt文件。

对于原有机构新增节点,真正决定成败的文件是cert/agencyA/agency.key和cert/agencyA/agency.crt。这两个文件代表该机构的上链身份,签发节点证书必须依赖它们。没有它们,后面的证书步骤基本没法做。

2.2 为什么机构私钥不能丢

机构私钥的重要性,很多人意识不到,直到出事才后悔。

某次接手一个老项目,对方想在原有机构内新增节点,但找遍服务器只找到agency.crt,agency.key怎么都翻不到。最后只能向CA重新发起一个机构证书,把旧机构的所有节点证书全部作废重签。这等于把整条链的机构身份更新了一遍,操作量直接翻倍,还伴随着业务中断风险。

所以,我的习惯是拿到FISCO BCOS环境的第一天,就把nodes/cert整个目录打包冷备份,放到两个不同的物理位置,并且只允许特定的人掌握密码。这个习惯可以帮你在后续扩容、证书续期、故障恢复时省掉绝大多数的麻烦。

2.3 端口规划与资源评估

新增节点最容易被忽略的就是端口冲突。

如果和已有节点同机部署,必须给新节点分配独立的P2P端口(2.0默认30300)和channel端口(默认20200)。RPC端口(默认8545)能不动就不动,一般新节点不需要开启对外RPC,除非有业务要直连它。

还要注意,即使只是横向扩容,新节点同样会参与群组内部的消息广播。节点之间是网状连接,网络带宽维度要额外评估,尤其多机房部署时,新增一个异地节点,跨机房的同步流量会同步增长。我当时给客户提的方案里,都会专门列一张资源检查清单:CPU核数、内存、磁盘IO、带宽、文件句柄数、端口占用情况,全部确认没问题再动证书。

3. 核心实操:证书签发与配置生成

3.1 为原机构补签发节点证书

假设环境如下。

节点根目录:/data/nodes 原机构名:agencyA 新增节点目录名:node2

在cert目录下运行工具脚本:

cd /data/nodes/cert ./gen_node_cert.sh -c agencyA -o /data/nodes/new_node_cert

-c指定机构名,-o指定证书输出目录。

运行完成后,输出目录里应该有node.crt、node.key,脚本通常还会顺带拷贝一份ca.crt。

接着把这些证书放到新节点的conf目录里:

mkdir -p /data/nodes/127.0.0.1/node2/conf cp /data/nodes/new_node_cert/node.crt /data/nodes/127.0.0.1/node2/conf/ cp /data/nodes/new_node_cert/node.key /data/nodes/127.0.0.1/node2/conf/ cp /data/nodes/cert/ca.crt /data/nodes/127.0.0.1/node2/conf/

这里要强调一点:必须重新生成证书,不能直接copy旧节点的node.crt和node.key。因为每个区块链节点必须有唯一的nodeID,nodeID由节点私钥通过椭圆曲线算法推导。如果直接copy旧节点证书,新节点和旧节点的nodeID就会完全一样,轻则权限混乱,重则节点互相冲突、被群组拒绝。私钥泄露的话,别人还能冒充这个节点参与共识,后果非常严重。

3.2 复制并调整config.ini

最简单的配置生成方式,是从已有节点拷贝一份,然后再改。

cp -r /data/nodes/127.0.0.1/node0/config.ini /data/nodes/127.0.0.1/node2/ mkdir -p /data/nodes/127.0.0.1/node2/data cp /data/nodes/127.0.0.1/node0/data/group.1.genesis /data/nodes/127.0.0.1/node2/data/ cp /data/nodes/127.0.0.1/node0/data/group.1.ini /data/nodes/127.0.0.1/node2/data/

然后重点修改config.ini里的三个部分。

第一是P2P配置,把listen_port改成新端口,再确认nodes列表:

[p2p] listen_ip=0.0.0.0 listen_port=30305 enable_compress=false nodes=192.168.1.10:30300,192.168.1.11:30301

这里有个技巧:nodes不需要把全网所有节点都填进去,只要填几个能够打通的“入口节点”。节点启动后会通过它们发现整个网络的节点拓扑,再以自己身份去建立其他连接。一般填同内网的几个稳定节点即可。

第二是channel和rpc配置,channel_listen_port必须改,否则同机端口被占用:

[rpc] channel_listen_ip=0.0.0.0 channel_listen_port=20205 jsonrpc_listen_ip=127.0.0.1 jsonrpc_listen_port=8545

jsonrpc_listen_port如果和本机已有服务冲突,可以改成其他值;如果不需要JSON-RPC,甚至可以不开。

第三是检查存储路径,确认指向新节点的data目录:

[group] group_data_path=/data/nodes/127.0.0.1/node2/data group_config_path=/data/nodes/127.0.0.1/node2/data [storage] type=rocksdb path=/data/nodes/127.0.0.1/node2/data

这里有个非常容易踩的坑:拷贝旧节点data下的group文件时,只拷贝group.1.genesis和group.1.ini这两个文件,不要拷贝其他缓存文件。如果旧节点data下还有LevelDB之类的数据库目录,千万不要连着一块拷过去,否则新节点启动时读取到一堆本地旧状态,可能和当前链高度对不上,最后出现各种诡异问题。

新节点的群组数据,最稳妥的办法是从零开始同步。复制真正的区块数据文件,反而容易造成“看起来高度一样,实际位点不一致”的情况。就让它把自己当成一个全新的节点,老老实实从网络里拉区块数据,这才是最干净的。

3.3 同步启动脚本和二进制

如果有start.sh和stop.sh,直接从旧节点拷贝过来:

cp /data/nodes/127.0.0.1/node0/start.sh /data/nodes/127.0.0.1/node2/ cp /data/nodes/127.0.0.1/node0/stop.sh /data/nodes/127.0.0.1/node2/

然后打开脚本看里面的二进制路径,保证指向node2目录下的fisco-bcos可执行程序。通常build_chain生成的节点目录里没有二进制,需要自己放,或者做一个软链接指向安装目录。

这里要特别留意节点二进制的版本。如果新节点二进制和旧节点不一致,启动后可能出现协议版本不兼容,P2P连接一直建立不起来,日志里反复报handshake失败。别问我怎么知道的,排查过两小时才发现两边二进制差了半个月的版本。

启动前顺便确认执行权限:

chmod u+x /data/nodes/127.0.0.1/node2/start.sh /data/nodes/127.0.0.1/node2/stop.sh

稳妥起见,先跑一下新节点二进制版本号,确认和现有节点一致再启动。

4. 把新节点加入群组

4.1 启动新节点,看连接状态

进入节点目录执行启动:

cd /data/nodes/127.0.0.1/node2 ./start.sh sleep 2 tail -f log/node2.log

日志里能观察到节点启动、证书加载、连接到peer的信息。如果配置正确,大概率会看到类似“connected to peer”的日志。此时新节点已经和网络连通,但它还不是群组成员,因此不会收到区块同步任务。

接下来要查询新节点的nodeID,有两种方式。

方式一,在节点服务器上用openssl从证书里提取公钥,再计算nodeID:

openssl x509 -in /data/nodes/127.0.0.1/node2/conf/node.crt -noout -pubkey | openssl ec -pubin -outform der | sha256sum | awk '{print $1}'

得到的一串十六进制就是nodeID,使用时需要在前面补上0x前缀。

方式二,用控制台连接一个已经在群组里的旧节点,执行:

[group:1]> getPeers

如果新节点已经和旧节点建立了P2P连接,这里就能看到它的NodeID。这种方式更保险,因为它是从链上网络视角直接看到的,不会因为本地计算格式问题而出错。

4.2 通过控制台把节点设为观察者

进入控制台目录:

cd /data/console ./console.sh

连接成功后,执行:

[group:1]> addObserver 0x这里的nodeID

addObserver提交后,群组会通过系统合约更新节点角色,观察节点不参与出块,但会同步所有区块。此时再看新节点日志,会发现区块高度开始增长。

这个过程会触发链上交易,所以控制台可能会返回一个交易哈希。如果返回的code不是0,说明没成功,需要查一下nodeID格式或网络状态。

4.3 观察节点追高后,再转共识节点

等新节点高度追上最新高度后,再把它转成共识节点:

[group:1]> addSealer 0x这里的nodeID

执行后返回code为0,说明提案通过。共识节点列表里大部分节点完成确认后,新节点就正式进入共识流程。

这里强调一下:不要一上来就addSealer。先让它把数据同步完。新节点如果一边同步一边参与出块,可能因为缺少交易上下文,导致出块异常或者产生视图切换问题。区块链节点不是越早加入共识越好,等它“看得懂账本”了再投票才科学。

之前有个项目扩容时贪快,新节点刚启动10分钟就addSealer,结果节点还在拉历史区块数据,共识消息一来它处理不过来,整个群组出块断断续续,最后又removeSealer重新等同步,白白折腾了一个小时。

4.4 验证最终状态

主要验证三件事。

第一,节点已经连上其他节点。执行控制台getPeers,能看到新节点的地址和端口。

第二,群组节点列表已经包含新节点nodeID。执行getSealerList或者getObserverList。

第三,区块高度持续增长,且和其他节点一致。执行getBlockNumber,对比旧节点和新节点,高度应该一致或者新节点正在追赶中。

在节点服务器上,还可以看日志确认共识参与情况:

tail -f /data/nodes/127.0.0.1/node2/log/node2.log | grep "+++"

能看到“++++++++”关键日志,表示该节点正常参与共识流程。看到这些,扩容操作基本可以宣告完成。

5. 常见问题与排查技巧实录

5.1 新节点一直同步不到高度

遇到最多的问题是节点启动后日志里没有高度增长,或者一直在原地不动。

多半是P2P连接没有建立成功。先在服务器上测试到对端的网络连通性:

telnet 对端IP 对端P2P端口

如果不通,排查防火墙、安全组规则。区块链节点是P2P双向连接,不是单向访问就够,所以两个方向的策略都要放通。

再看config.ini里nodes列表是否填了可用入口节点。如果填的是自己,也就是新节点自己的IP和端口,就可能形成自连接,其他节点又不知道新节点的入口,全网找不到它,自然同步不了。

如果是跨云或者不同VPC之间部署,还要检查双向路由策略。我见过一个案例,节点所在机器的出方向网络正常,但入方向被安全组默认拒绝,结果节点能连别人,别人连不上它,同步一直卡在启动阶段。

5.2 addObserver失败,或节点一直不在列表里

一种情况是控制台连接通道有问题。控制台通过channel端口连接节点,如果新节点的channel端口和证书配置不对,控制台根本连不上,更别提交操作。经常出现的报错是Connection refused,或者证书校验失败。

一种情况是nodeID格式不对。少了0x前缀,或者从别处复制nodeID时带了换行符,系统合约不会直接报错,但操作会被忽略。排查时先执行getObserverList,看看当前有哪些observer,确认到底有没有加成功。

还有一种隐蔽情况:你addObserver时,事务确实提交了,但共识节点没有完成投票。联盟链的系统合约变更需要足够多共识节点在线确认,如果此时旧节点里有几个掉线,或者网络分区,操作会一直处于未确认状态。可以查看日志里的交易执行结果,确认是否超时。

5.3 证书校验失败或机构不匹配

FISCO BCOS 2.0默认节点证书有效期比较长,但如果你在证书签发时手动指定了很短的有效期,新增节点就会出现能启动、但和其他节点握手时证书校验失败的情况。日志里会有类似“certificate verify failed”的表现。这种情况只能重新用旧机构私钥签发一个长期有效的节点证书,再替换重启。

另外,不要把其他机构的agency.crt当成ca.crt放进conf。机构证书和CA证书的作用不一样,放错了会导致TLS握手失败。如果怀疑放错,把conf目录下三个crt文件全部重新检查一遍,确保一一对应。

5.4 新节点加入了不该加的群组

FISCO BCOS 2.0支持并行多组。如果业务分了group1、group2,而新节点只需要加入group1,那么它只需要拷贝group.1.genesis和group.1.ini。如果顺手把group2的数据也拷过来了,它会尝试加入两个群组。

这不是绝对错误,但要注意资源规划。多个群组同时同步,CPU、内存、磁盘都会成倍消耗。我遇到过新节点启动后CPU一直100%,查了半天才发现它同时加入了三个群组,在同时拉三条链的数据。

所以,新增节点前先想清楚:这个节点到底要不要同时参与多个群组。只要一个群组,就只拷贝一个群组的配置文件。

5.5 新节点要移除怎么办

如果新节点出了问题,想移除,不能直接删目录了事。直接删目录会导致群组共识节点列表里还留着这个节点,其他节点一直认为它在线,最终卡出块。

正确流程分三步。

第一步,如果是共识节点,先在控制台把它从共识节点列表移除:

[group:1]> removeSealer 0x这里的nodeID

第二步,再把它从观察节点列表移除:

[group:1]> removeObserver 0x这里的nodeID

第三步,停止进程,然后隔离节点目录:

cd /data/nodes/127.0.0.1/node2 ./stop.sh mv /data/nodes/127.0.0.1/node2 /data/backup/node2_$(date +%Y%m%d)

不同小版本的控制台命令名可能稍有差异,有的版本用removeSealer,有的版本走系统合约接口,操作前先查看对应版本的命令帮助,或者执行help确认。

我见过同事想直接删节点目录,结果新节点还留在群组共识列表里,整个群组一直认为有一个无法连接的节点在参与出块,出块一直卡了好几分钟,最后只能通过重新拉起节点才恢复。所以删除节点也一定要走控制台接口,别暴力拆。

最后说点个人经验。原有机构内新增节点,听起来是运维人员才会干的活,但业务方和合约开发者最好也清楚这个流程,毕竟容量规划、节点准入策略这些事,越早了解,越能让链上的里程碑计划不踩坑。我自己经历过一次以为只是加一个节点、结果折腾了一晚上证书的教训之后,现在每次扩容前都先做三件事:备份cert目录、确认端口占用、记录当前所有节点高度。准备工作到位了,真正动手只需要十几分钟。宁可慢一点,别给链上留隐患。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询