
FISCO BCOS 的联盟链跑了一段时间机构A发现群组里的共识节点数量不够或者想在不引入新机构的前提下增加一个只读节点分担查询压力于是想到了在原有机构内新增节点。我第一次做这件事的时候第一反应是把现有节点的目录复制一份改改IP和端口再启动就行结果节点一直连不上群组日志里全是证书校验失败。后来才搞清楚一个核心问题FISCO BCOS里节点身份是由证书和nodeid共同唯一确定的复制出来的节点在链上仍然是同一个身份扩容等于没扩。这篇文章就围绕原有机构内新增节点这个诉求从证书签发、节点配置、群组接入、状态验证到常见事故复盘完整走一遍实操路径。内容以2.x版本为主也会兼顾3.x的差异适合正在维护FISCO BCOS网络、准备做节点扩容的运维同学参考。1. 扩容之前先想清楚新增节点到底在解决什么问题1.1 一个节点一个身份复制旧节点没有用FISCO BCOS 节点的身份由两样东西决定证书链中的节点证书以及由节点私钥生成的 nodeid。即便你把一个旧节点的整个目录原封不动复制到新机器上它的 nodeid 不会变在链上依然被识别成同一个节点。这带来的后果是节点视图、共识节点数、容错能力统统没有任何变化只是换了个IP在跑。所以原有机构内新增节点的本质不是多部署一个进程而是为原机构生成一个全新的节点身份并让链上群组认识这个身份。身份合法性的根子在于证书——必须由本机构的agency证书签发新节点证书其他节点才会认可它。这一步没有做好后面的一切都白搭。1.2 扩容前必须确认的信息清单动手之前我建议先把下面这些信息核对清楚否则后面很容易来回返工。确认项确认方式为什么重要链版本二进制目录下执行./fisco-bcos --version2.x和3.x的证书工具、控制台命令、配置结构差异较大群组编号查看节点目录下的group.*.genesis文件默认是group0新节点必须加入正确的群组现有节点列表查看任意节点 config.ini 中的[p2p]段新节点需要知道所有对端地址才能建立连接原机构证书位置部署时保留的nodes/cert目录签发新节点证书必须用到其中的agency证书新节点角色业务诉求决定是参与共识还是只做同步和查询新机器端口和现网端口做对比P2P、channel、jsonrpc三类端口都不能冲突对于为什么不能用全新的一套证书可以这样理解FISCO BCOS 联盟链的信任边界从根证书就开始了。链上所有节点共享同一个ca根证书各机构的agency证书又是由ca签发的。如果你自作主张生成一套新的根证书给新节点用它在做SSL握手时就会因为根证书不匹配而被其他节点直接拒绝日志里全是握手失败。2. 证书是绕不开的第一关用原机构证书签发新节点身份2.1 证书链的层级关系FISCO BCOS 2.x 的证书体系是树形结构从上到下是CA根证书整条链的信任起点所有节点的ca.crt必须一致机构证书agency由CA签发代表一个机构节点证书node由对应机构的agency证书签发绑定一个节点的身份。一个节点要加入原有群组必须同时满足两个条件一是ca.crt和链上其他节点一致二是node.crt由该机构自己的agency签发。如果把机构A的证书发给机构B的新节点用证书链在SSL层可能能通过校验因为根一致但在群组准入和后续的协议处理中有可能被其他节点判定为身份异常行为不可预期。2.2 生成新节点证书的完整操作如果当初是用build_chain.sh部署的并且保留了nodes/cert目录那里面会有ca.crt、agency.crt、agency.key等文件。签发新节点证书用官方脚本gen_node_cert.sh基本用法如下# 进入工具脚本所在目录旧版本脚本一般在 build_chain.sh 同目录 bash gen_node_cert.sh -c nodes/cert -o newCertDir -n agencyA参数解释-cagency证书所在目录必须包含ca.crt、agency.crt、agency.key-o输出目录脚本会自动创建-n机构名要和原机构一致不要随意改名。执行成功以后在newCertDir目录下至少能看到newCertDir/ ├── node.crt ├── node.key └── node.nodeid其中node.nodeid就是后面要用控制台加入群组的身份串。提示不同小版本的工具脚本参数可能不完全一样最稳妥的做法是拿到脚本后先执行bash gen_node_cert.sh -h看一眼帮助说明再动手。2.3 证书使用时最容易被忽略的点一是私钥权限。node.key是节点的私钥文件部署到生产服务器后建议设置为仅节点用户可读写避免被同机器其他账号读取。二是证书备份。整个nodes/cert目录应当单独离线备份一旦丢了agency.key后续新增节点、更换节点证书都会非常被动。三是机构名一致性。gen_node_cert.sh里的-n参数如果写错虽然证书链可能仍然校验通过但在某些版本的准入检查里会遇到隐性问题排查起来很隐蔽。3. 搭建节点实例目录结构、config.ini与端口规划3.1 初始化节点目录拿到新证书后接下来要把一个完整可启动的节点实例搭出来。推荐的思路是以现有某个节点的目录为模板复制一份但必须删掉旧的证书文件再放入新签发的证书。以2.x版本为例一个单群组节点的标准目录结构是nodes/ └── 192.168.1.15/ ├── config.ini ├── fisco-bcos ├── group.0.genesis ├── group.0.ini └── conf/ ├── ca.crt ├── agency.crt ├── node.crt ├── node.key └── node.nodeid操作步骤如下# 复制模板目录 cp -r nodes/192.168.1.10 nodes/192.168.1.15 # 删除旧证书 rm -f nodes/192.168.1.15/conf/node.crt rm -f nodes/192.168.1.15/conf/node.key rm -f nodes/192.168.1.15/conf/node.nodeid # 放入新证书 cp newCertDir/node.crt nodes/192.168.1.15/conf/ cp newCertDir/node.key nodes/192.168.1.15/conf/ cp newCertDir/node.nodeid nodes/192.168.1.15/conf/ca.crt和agency.crt可以沿用原节点目录里的因为整条链共用同一个ca同一个机构共享同一个agency证书。3.2 config.iniP2P和RPC配置config.ini 是节点的核心配置文件新增节点时需要重点修改[p2p]和[rpc]两段。[p2p] # 新节点的监听IP和P2P端口 listen_ip0.0.0.0 listen_port30300 # 当前链上所有已存在的节点地址至少写全已连接的对端 node.0192.168.1.10:30300 node.1192.168.1.11:30300 node.2192.168.1.12:30300 [rpc] # 控制台通过channel端口连接节点新节点的channel端口不要和其他节点冲突 channel_listen_port20200 # jsonrpc端口按需开启冲突时一样要改 jsonrpc_listen_port8545P2P段里的node.0、node.1等配置是节点启动后主动去连接的对端地址。新增节点时建议把当前链上所有节点的P2P地址都列全不要只填一两个。原因很简单如果只连一个对端一旦这个对端掉线新节点可能找不到足够多的peer继续同步区块数据。3.3 群组配置genesis文件和动态准入的边界很多第一次做扩容的人会在group.0.genesis里手动添加新节点的nodeid这在FISCO BCOS 2.x里是不推荐的。group.0.genesis是由创世块决定的初始节点列表链在部署时就已经确定。后续新增节点正确做法是启动节点后通过控制台的群组管理命令动态添加。新节点只要拥有正确的group.0.genesis和group.0.ini启动后就能通过现有节点同步到最新的群组视图。这里需要特别说明一下动态准入的机制控制台执行的addSealer或addObserver本身是一笔群组内的交易它会被打包进区块并同步给全链节点。新节点启动并连上网络后通过同步拿到这笔交易就知道自己已经进入群组。这个过程并不需要手工去改genesis文件。3.4 端口规划的几个坑先检查机器上是否已经有节点进程占用端口。常见默认端口是P2P的30300、channel的20200、jsonrpc的8545。如果新节点和现有节点在同一台机器上必须全部错开。另外跨机房部署时要确认网络ACL放行了P2P端口和channel端口很多扩容后节点连不上的问题最后一查都是防火墙只放行了业务端口忘了放P2P端口。4. 把新节点接入群组addSealer与addObserver的完整操作4.1 拿到新节点的nodeid先进入新节点目录读取nodeidcat conf/node.nodeid输出是一长串64字节的十六进制字符串看起来类似0a0e1f2c3b4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f后面所有控制台操作都用这串字符串。4.2 观察节点还是共识节点先做选择控制台提供了两个关键命令addSealer nodeid # 将节点加入共识节点列表 addObserver nodeid # 将节点加入观察节点列表如果你现在只想让新节点分担查询流量、同步全量账本那就选addObserver。如果想让新节点参与PBFT共识、提升容错能力选addSealer。区别在于观察节点只同步区块不参与出块共识节点要参与每轮投票和出块流程对机器性能、网络延迟的要求更高。4.3 实际操作顺序在任意一台现有节点机器上启动控制台cd ~/fisco/console bash start.sh连接成功后依次执行# 先把新节点加为观察节点 addObserver 0a0e1f2c3b4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f # 查看观察节点列表确认加入成功 getObserverList # 如果目标是共识节点等区块同步追平后再升级 addSealer 0a0e1f2c3b4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f # 查看共识节点列表 getSealerList # 查看群组内所有节点ID getNodeIDList执行addSealer或addObserver之后控制台一般会返回一个交易hash或成功标识。此时并不代表节点一定能立刻正常参与共识你还需要等待区块打包这笔交易并观察新节点的实际同步状态。4.4 关于共识容错的一个数学提醒扩容决策里最容易出问题的是对PBFT容错的理解。FISCO BCOS 2.x默认使用PBFT共识对N个共识节点的群组可容忍的故障节点数 f 满足N 3f 1也就是 f 最大取(N-1)/3向下取整。简单列一个对应关系共识节点总数 N可容忍故障节点数 f说明10单节点谈不上容错41最常见的生产起步配置51增加1个节点容错能力没有变化72想容忍2个故障节点至少需要7个共识节点所以加一个共识节点就能提升容错是个常见误区。如果机构当前群组是4个共识节点目标是容忍2个节点同时故障那需要的是扩容到7个而不是5个。如果你不提升f数单纯加节点反而会让PBFT消息复杂度增加出块延迟可能变大。这也是为什么我在扩容前一定会确认到底为什么要加节点——为了容错还是一个只读节点。5. 启动与验证区块同步、共识参与和日志核对5.1 启动新节点配置全部就绪后在新节点目录下启动cd nodes/192.168.1.15 nohup ./fisco-bcos -c config.ini node.log 21 生产环境最好用systemd或类似工具做进程守护避免进程异常退出后没人拉起。启动后先看日志确认进程没有报错tail -f node.log正常启动时日志里会出现节点启动信息、监听端口信息随后会尝试和config.ini里配置的P2P对端建立连接。5.2 验证连接与区块同步关键验证分三步第一步看P2P连接。日志中搜索connected或者peer确认新节点和现有节点已经建立连接。连接数为0基本等于没接上链要回头看P2P配置和防火墙。第二步对比区块高度。回到控制台执行getBlockNumber分别在新节点连接到的某个现有节点以及新节点自身如果新节点也开了channel端口上查询区块高度。新节点启动后区块高度会从0或创世高度开始逐步追上现有节点的最新高度。如果长时间不增长重点检查P2P连接数是否过少、对端节点是否真的填全了。第三步看是否开始参与共识。如果目标是共识节点观察新节点日志看到持续出现视图切换、commit等相关日志说明它已经在参与共识流程了。如果目标是观察节点能看到它持续同步新区块即可。5.3 我推荐的生产操作顺序先观察后共识在多次扩容实操中我最推荐的安全顺序是新节点先以addObserver加入群组启动新节点等它的区块高度完全追上现有节点观察一两轮正常出块节奏之后再执行addSealer升级为共识节点。这样做的原因是如果新节点在区块高度还落后一大截时就直接进入共识节点列表PBFT共识在它那里会因为缺少最新状态而产生大量视图切换或超时极端情况下会导致群组出块暂停。先以观察者身份同步等于给新节点一个热身过程风险小得多。6. 扩容实战中的高频事故证书冲突、端口占用与共识卡死6.1 SSL握手失败或证书校验失败现象新节点日志不断出现sslConnect failed、verify peer cert failed之类的报错节点始终连不上现有节点。根因绝大多数情况是证书链不匹配。比如新节点的ca.crt和链上其他节点不一致或者node.crt不是当前机构agency签发的又或者直接复制了旧节点证书。排查顺序先对比新节点与现有节点的ca.crt是否一致再确保证书确实是由gen_node_cert.sh基于原机构证书签发的。发现不匹配只需要把正确证书重新放到conf目录并重启。6.2 端口冲突与bind失败现象进程启动后瞬间退出日志里有bind failed或者address already in use。根因P2P端口、channel端口或jsonrpc端口被现有进程占用。排查用netstat -lnp | grep port查看端口占用情况修改config.ini里的对应配置即可。同一机器多节点时建议在目录命名和配置注释里把端口写清楚否则时间一长容易混。6.3 nodeid重复群组里出现两个一样的身份现象控制台getSealerList里看不到新增的nodeid或者发现已有节点和新节点nodeid相同。根因直接把旧节点证书复制过来了。复制目录时忘了删除conf目录下的node.crt、node.key、node.nodeid导致新节点身份和旧节点完全一样。排查对比新旧两个节点的conf/node.nodeid如果一致就是复制遗留。删除新实例中的旧证书换上新签发的证书重启。6.4 加完共识节点后出块变慢或暂停现象群组getBlockNumber长时间不增长其他节点日志里持续出现视图切换。根因新共识节点区块高度落后或者新节点和其他节点网络不稳PBFT共识无法达成一致。处理方案先用控制台执行removeNode或addObserver把新节点从共识节点列表里摘除恢复出块等确认新节点同步到最新高度后再重新addSealer。这个回滚操作是动态的不用重启其他节点但操作前最好记录当前群组节点视图。6.5 一个必须养成的习惯操作前打快照每一次addSealer、addObserver、removeNode都会改变群组节点视图属于链上状态变更。虽然FISCO BCOS支持动态管理但生产环境依赖的是稳定我会建议在变更前对现有节点目录、证书目录、控制台配置做一次完整备份。尤其是私钥和证书体系宁可多备份一份也不要等出了问题再四处找。最后再分享一个小技巧如果你的环境里存在多套测试链尽量给每套链的节点目录、证书目录都标注清楚对应关系不要混用。我在一次压测环境里就吃过这个亏——用了另一套链的ca目录签发节点证书结果新节点怎么都连不上目标链排查了一个多小时才发现是根证书对不上。扩容这件事本身并不复杂但每一步都依赖证书、配置、身份的正确组合任何一环错了表现出的现象都可能很相似。按本文的路径走一遍大部分问题都能在动手前提前规避。