
链子搭起来了控制台也能发交易了节点日志“Consensus模块出块成功”刷得飞起——但这时候如果有人问你链上现在到底有多少个区块那笔转账的交易哈希是多少某个地址的余额变化曲线长什么样你总不能去翻节点日志一条条对。FISCO BCOS 系列的这一篇我就想聊聊怎么把这层“黑盒”捅破也就是给链配一个区块链浏览器。这个系列面向的读者是已经把 FISCO BCOS 单机链跑起来、打算继续往应用方向走的开发者。这次讲的内容能让你在一个下午内搭出一个界面化、可查询、可监控的链上数据可视化平台。1. 为什么链上数据必须有个“看得见的窗口”1.1 节点里存的数据并不是人眼能直接读的FISCO BCOS 的节点本身是用 C 写的核心就是共识、同步、交易执行、状态存储这几件事。它把数据存在节点本地的 leveldb 里区块头和区块体分开存交易内容经过 RLP 编码后落盘。你要是直接把某个区块文件拖进文本编辑器看到的是一堆十六进制串和二进制乱码。这就带来一个非常现实的问题区块链的一切价值都建立在“可验证、可追溯”上可普通用户、业务方、甚至是审计人员根本没能力直接去解析 RLP 编码、去比对 state root。节点对外虽然有 JSON-RPC 接口比如getBlockByNumber、getTransactionByHash但你要靠手敲命令来查数据效率低不说还容易敲错。我在实际项目里遇到过这样的场景客户要演示“存证上链”的效果领导坐在旁边问“交易在哪儿呢给我看看”。你总不能把终端窗口怼到领导脸上给他看一条curl返回的十六进制结果。这种尴尬时刻多了你就会明白链上数据必须要有一层面向人的“翻译官”把区块、交易、事件、账户状态这些底层数据转换成表格、列表、图表让任何人都能看得懂。1.2 浏览器到底解决了什么查询、统计、监控区块链浏览器的核心价值我总结下来是三件事。第一是查询。给一个交易哈希能查到这个交易在哪个区块里、由谁发起、调用了哪个合约、消耗了多少 gas给一个区块高度能看到这个块里的所有交易明细给一个合约地址能看到它的代码、创建时间、最近的活动记录。这个能力是区块链浏览器的底线做不到这个其他都白搭。第二是统计。单笔交易可以靠哈希查但如果你想看“过去一小时链上交易量的趋势”或者“最近100个区块平均出块时间有没有抖动”靠单个接口一遍遍轮询是不现实的。浏览器会定时把链上数据同步到自己的数据库里然后做聚合统计展示出首页那些区块高度、交易总数、节点状态、出块时延之类的图表。第三是监控。联盟链是要长期运营的节点 CPU 高不高区块高度跟别的机构节点差了多少共识有没有异常这些状态如果依赖人工登录服务器去盯迟早出问题。浏览器把节点的心跳、块高、共识状态都拉到界面上运维人员打开页面扫一眼就心里有数。理解了这三点你就知道为什么每个区块链项目落地几乎都要配一个浏览器。它不是锦上添花而是基础设施。2. FISCO BCOS 生态里的浏览器组件选型时别搞混2.1 官方主推的 WeBASE 到底是什么FISCO BCOS 生态里跟“浏览器”相关的方案最容易让新人迷糊因为名字太多了。我先帮你把关系理清。官方最推荐、也是社区里用得最多的是 WeBASE全称是 WeBank Blockchain Application Software Extension中文叫“微众区块链应用扩展组件”。它不是一个单一的程序而是一套微服务架构下的应用平台里面包含了节点前置、管理服务、网页端、签名服务等多个子组件。你平时说的“区块链浏览器”在 WeBASE 这套体系里其实就是WeBASE-Web这个前端页面再加上它背后负责取数、落库、提供 API 的WeBASE-Node-Manager和WeBASE-Front。另外还有一个名字非常直白的项目叫 BlockChain Browser这是 FISCO BCOS 早期官方的一个独立浏览器项目主要功能就是展示区块、交易、节点信息。但它的开发和维护基本处于停滞状态新版本链上跑它容易遇到兼容性问题。我不建议新项目再用这个除非你有特殊的历史包袱。社区里还有一些个人开发的轻量级浏览器有的基于 Spring Boot 写后端、Vue 写前端有的干脆用 Python Flask 做了个极简版。这类项目的好处是轻、好懂适合学习坏处是功能不全、没人长期维护、链版本一升级可能就废了。我一般不推荐生产环境用但如果你只是想快速验证某一个功能拿来参考参考思路也不错。2.2 组件角色划分与通信链路为了让你后面部署时不至于不知道自己在做什么我先把 WeBASE 这套组件之间的调用关系讲透。这有点像一个公司里的三层组织结构。最底层的 FISCO BCOS 节点是“干活的人”所有的数据写入、共识、存储都在这里发生。节点对外开了一个channel 端口建链时-p参数里那个 20200 就是 channel 端口专门用于 SDK 跟节点之间的通信注意不是 8545 那个 JSON-RPC 端口。中间层是WeBASE-Front也就是节点前置。它做的事情是拿着节点签发的一套 SDK 证书通过 channel 端口跟节点建立安全的 SSL 连接把节点的 RPC 能力包装成一堆更友好的 RESTful API。同时它本身也自带一个简单的网页可以用来部署合约、调用合约、查看最近出块情况。你可以把 Front 理解成“节点门口的接待处”——它能直接跟节点对话但只是单节点的窗口不负责全局的数据汇总。再往上是WeBASE-Node-Manager它是整套系统的“数据中心”。它做的事情很朴素但非常关键定时用 Front 提供的接口拉取最新区块、解析交易、把解析结果写进 MySQL。前端页面所有的查询、统计、图表数据都是从 Node-Manager 的接口拿的。最上面的WeBASE-Web就是你在浏览器里看到那个页面纯前端工程通过 nginx 或者直接访问IP:5000来加载。WeBASE-Sign则是可选的签名服务主要用来统一托管私钥、提供交易签名接口方便业务系统调用。如果你只是搭浏览器看看链上数据Sign 不是必须的但如果你后续要做业务系统对接链它基本是标配。我把这几个组件的角色和端口列个表你理解起来会更直观组件角色默认端口必须部署FISCO BCOS 节点底层链、数据存储、共识30300 / 20200 / 8545是WeBASE-Front节点前置封装 RPC 为 RESTful5002是WeBASE-Node-Manager数据同步、统计、提供查询 API5001是WeBASE-Web前端展示页面5000nginx是WeBASE-Sign私钥托管与交易签名5004按需注意默认端口只是约定你在配置文件里都是可以改的但如果你没有特别的端口冲突问题建议保持默认这样出问题的时候查资料、看日志都对得上号。3. 开始部署前的环境检查和版本搭配3.1 版本搭配为什么建议 JDK8 MySQL 5.7WeBASE 这套组件是用 Java 写的所以环境准备的第一步就是 JDK。这里我必须专门强调一下版本老老实实用 JDK 1.8。虽然现在 Oracle 都已经把 JDK 8 列为老古董了但 WeBASE 在编译和运行时对 JDK 版本是敏感的直接用 JDK 11 或者 17 去跑很容易出现启动报错比如一些依赖库反射失败、模块访问权限问题之类的。生产求稳JDK 8 是唯一不会给自己添堵的选择。数据库方面官方文档写得比较保守支持 MySQL 5.6 及以上但我个人的实际经验是MySQL 5.7 是最稳的。MySQL 8.0 不是不能用但它默认的认证插件是caching_sha2_password而 WeBASE 的数据库连接池不一定带对应的驱动容易踩“Public Key Retrieval is not allowed”这种莫名其妙的坑。如果你对 MySQL 8.0 的调优不熟就听话用 5.7。操作系统方面CentOS 7.x 和 Ubuntu 16.04/18.04 都是官方验证过的环境我自己常用的是 CentOS 7.9。因为 FISCO BCOS 建链脚本 build_chain.sh 依赖的很多东西在 CentOS 上装起来最顺手而且 WeBASE 的部署脚本对 systemd 的依赖也不强用nohup托管进程就够了。3.2 部署前的检查清单我给你的建议是在下载任何组件之前先花十分钟把环境过一遍。下面这几条几乎是我每次部署都要检查的固定动作检查 Java 版本java -version确认是 1.8 而不是 17检查 MySQL 版本mysql -V确认是 5.7确认 MySQL 允许远程连接后续 WeBASE-Front 和 Node-Manager 可能要连至少bind-address不能只限定 127.0.0.1确认防火墙放行端口30300、20200、8545、5000、5001、5002、5004确认安装wget、curl、unzip之类的基础工具没有的话先yum install -y装上确认能访问外网因为无论是下载 FISCO BCOS 的建链脚本还是从 Gitee 拉 WeBASE 的安装包都需要网络。提示如果你用的是云服务器防火墙规则别只改系统内部的 iptables/firewalld安全组里那几个端口也要同步放行。这个坑我踩过不止一次系统防火墙全开了结果安全组没放行端口死活连不上。3.3 建链脚本的简要回顾WeBASE 是给“已经跑起来的链”做可视化的所以你得先有一条 FISCO BCOS 链。如果你是从零开始先用官方脚本建一条 4 节点的链curl -#LO https://osp-1257653870.cos.ap-guangzhou.myqcloud.com/FISCO-BCOS/FISCO-BCOS/releases/v2.9.1/build_chain.sh chmod ux build_chain.sh bash build_chain.sh -l 127.0.0.1:4 -p 30300,20200,8545-p后面三个端口分别对应 P2P 端口节点间通信、channel 端口SDK 连接、JSON-RPC 端口HTTP 调用。后面 WeBASE-Front 连节点用的就是中间的 channel 端口。建完链之后启动节点然后快速验证一下bash nodes/127.0.0.1/start_all.sh tail -f nodes/127.0.0.1/node0/log/log* | grep 看到日志里不断出现出块标志说明链已经处于正常共识状态。到这个阶段环境准备就算完成了。4. 一步一步部署 WeBASE四个组件的配置细节4.1 下载安装包并规划目录WeBASE 的安装包在 Gitee 的 WeBASE 仓库里都有对应的 Release 包名字规律很清楚比如webase-front.zip、webase-node-mgr.zip、webase-web.zip、webase-sign.zip。下载的时候注意对应你 FISCO BCOS 的版本。如果你链是 2.9.x就下载 v2.9.x 对应的 WeBASE 组件。我用一个统一的目录来放所有组件方便管理比如/data/webase。解压之后大概是这个结构/data/webase/ ├── webase-front/ ├── webase-node-mgr/ ├── webase-web/ └── webase-sign/4.2 WeBASE-Front 的配置与证书拷贝WeBASE-Front 是整条链路里最贴近链的组件核心就是证书配置。FISCO BCOS 节点之间、SDK 与节点之间的通信是双向 TLS 认证的所以 Front 必须持有节点签发的 SDK 证书才能通过 channel 端口连接节点。找到你建链目录下的证书文件nodes/127.0.0.1/sdk/ ├── ca.crt ├── node.crt └── node.key把这三个文件拷贝到webase-front/conf/目录下覆盖掉原来的同名文件。然后修改conf/application.ymlserver: port: 5002 sdk: host: 127.0.0.1 port: 20200 # 如果链是国密模式这里要写加密套件配置非国密无需关心这里有两个容易出错的地方。第一host要写节点所在机器的 IP如果你 Front 和节点在不同机器要写节点内网 IP 而不是 127.0.0.1。第二国密链和非国密链的证书位置不同国密链的 SDK 证书在nodes/127.0.0.1/sdk/gm目录下里面是gmca.crt、gmsdk.crt、gmsdk.key这几个文件而且配置里还要额外设置encryptType: 1。非国密链不用管这个字段或者显式写 0。4.3 初始化数据库并部署 Node-ManagerNode-Manager 需要 MySQL 实例而且首次部署必须先建库、导表。WeBASE 的源码包不是编译好的 zip 包里有 SQL 初始化文件路径在webase-node-mgr/script/下。不过为了省事官方编译好的webase-node-mgr.zip里也带了webase-node-mgr.sql和webase-node-mgr-data.sql。用命令初始化# 登录 MySQL建库 mysql -uroot -p CREATE DATABASE IF NOT EXISTS webasenodemanager DEFAULT CHARACTER SET utf8; exit # 导入表结构和初始数据 mysql -uroot -p webasenodemanager webase-node-mgr.sql mysql -uroot -p webasenodemanager webase-node-mgr-data.sql然后改webase-node-mgr/conf/application.yml里的数据库连接信息spring: datasource: url: jdbc:mysql://127.0.0.1:3306/webasenodemanager?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: 你的密码注意Node-Manager 在启动时会自动调用 Front 的接口去拉数据所以必须先启动 Front再启动 Node-Manager。顺序反了Node-Manager 虽然能起来但日志里会一直刷“无法连接前置服务”的错误页面也是一片空白。4.4 启动 WeBASE-Web 前端WeBASE-Web 不需要编译解压后就是一个静态资源包。官方推荐的做法是用 nginx 来托管并且把接口请求代理到 Node-Manager 的 5001 端口。nginx 配置类似这样server { listen 5000; server_name localhost; location / { root /data/webase/webase-web/; index index.html; try_files $uri $uri/ /index.html; } location /api/ { proxy_pass http://127.0.0.1:5001/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }这里我把 Node-Manager 的接口请求统一转发到/api/前缀下前端页面发请求时也会拼上这个前缀。如果你不想配 nginx也可以直接把webase-web的static目录用 Python/http-server 起个静态服务然后在页面配置文件里写死接口地址。但第一负载均衡、第二跨域问题nginx 一步到位解决掉所以我劝你别省这个事。全部启动之后访问http://服务器IP:5000就能看到 WeBASE 的登录页了。默认管理员账号和密码在你初始化数据库的 data 脚本里写死了常见的默认配置是admin/Abcd1234首次登录后赶紧改掉。5. 部署完成后的连接链路与数据上链验证5.1 页面到节点服务的完整调用链路当你在 WeBASE-Web 页面上点了一下“查看最新区块”背后其实走了一条很长的调用链。你作为运维者必须心里清楚这条链是通的才会有排查的方向。前端页面发起请求到 nginxnginx 把/api/开头的请求转发给 Node-Manager 的 5001 端口。Node-Manager 收到请求后先去 MySQL 里查它已经同步好的区块数据返回给前端展示。与此同时Node-Manager 后台有个定时任务会周期性调用 Front 的接口5002 端口拉取链上的最新块高。Front 拿到请求再通过 channel 端口 20200 去问真正的 FISCO BCOS 节点要数据。所以你在页面上看到的任何一个“最新块高”理论上可能落后真实链上一两个块——因为中间隔了一层定时同步的延迟。这不是bug是架构设计的取舍。如果业务上需要实时性极强的数据Node-Manager 的定时轮询间隔可以调短但代价是数据库压力增大。5.2 用控制台造一笔真实交易并验证浏览器搭好之后光看空的链没有意义我们造点真实数据来验证整条链路。先用控制台部署一个简单的合约。进到 FISCO BCOS 的控制台目录cd ~/fisco/console cp conf/applicationContext-sample.xml conf/applicationContext.xml # 把证书拷到控制台 conf/ 下 cp ~/fisco/nodes/127.0.0.1/sdk/* conf/ bash start.sh然后执行[group:1] deploy HelloWorld拿到合约地址后再调用set方法写入一个值。回到 WeBASE-Web 页面刷新首页你会看到区块高度涨了几个交易数量也增加了。在搜索栏里输入刚才调用返回的交易哈希能找到这条交易的完整信息包括发起方、接收方合约地址、输入数据十六进制编码的set参数、区块高度、时间戳。这个验证过程看起来简单但它同时验证了整条链路的所有环节节点打包出块正常、Front 通过 channel 拉取正常、Node-Manager 解析和落库正常、Web 页面查询接口正常。任何一环有问题这个验证过程都会在某一步卡住。5.3 浏览器页面里值得长期关注的信息位部署完成之后你日常维护链的时候有几个信息位我强烈建议你养成习惯去看首页的节点列表每个节点的块高应该基本一致如果某个节点块高落后特别多说明它同步出问题了出块周期统计FISCO BCOS 共识出块时间正常情况下是比较稳定的如果某个时间段的出块时间突然拉长可能是节点性能下降或者某些机器上的共识线程有问题合约列表你部署了哪些合约、最新调用时间是什么时候这些信息对审计很有用平时不看真到复盘的时候才想起来查就晚了审计日志/操作记录如果你给运营人员开了账号所有的登录、查询、操作行为都在系统里留痕这本身也是联盟链合规的一部分。6. 高频报错排查这五类问题我基本都遇到过6.1 数据库连接失败 / 初始化失败现象启动 Node-Manager 后日志里报Communications link failure或者Access denied for user。排查链路先确认 MySQL 服务有没有起来用systemctl status mysqld看一眼再确认账号密码对不对注意 URL 里的编码字符密码里如果带了、、#之类的特殊字符要在 URL 里做转义不然会被连接串错误解析掉最后确认 MySQL 账号有没有远程登录权限默认 root 可能只允许本地登录。实际上我在第一次部署时就因为密码里有个导致连接串解析到错误主机报错非常迷惑。后来把密码改成无特殊字符的纯字母数字组合一次通过。教训是基础设施类软件的密码别追求复杂追求稳定。6.2 Front 连不上节点现象Front 启动后日志报错客户端握手失败或者提示connect to 127.0.0.1:20200 failed。排查链路先用命令行验证端口通不通telnet 127.0.0.1 20200。端口通就查证书——证书没拷对是 head 号问题。注意 FISCO BCOS 节点的 SDK 证书是随节点初始化生成的不能把节点的 ca.crt 拿来代替 sdk 目录下的 ca.crt两者虽然同名但用途不同。最简单靠谱的做法就是老老实实从nodes/127.0.0.1/sdk/目录拷贝别从别的节点目录里顺手抄一份。还有一种是国密链的坑你建链时加了-g参数启用了国密那 Front 的application.yml里就要配置加密套件否则握手必然失败。很多新手拿着非国密的教程去配国密环境折腾半天都是在做无用功。6.3 Node-Manager 页面没数据现象页面能打开登录也正常但首页上所有数据都是 0块高不涨交易列表为空。排查链路先看 Node-Manager 日志确认“拉取区块”的定时任务有没有在跑。如果日志里没有任何拉取动作多半是配置里的frontIp和frontPort写错了指向了不存在的 Front。如果日志里有拉取动作但数据库中确实没有数据很可能是 Front 返回的数据解析失败这时候去看 Front 的日志看它跟节点的通信是否正常。还有一种情况容易忽略页面里选的群组不对。FISCO BCOS 一个链上可以有多个群组Node-Manager 拉数据是按群组维度拉的。你如果建链时建了 group1、group2 两个群组而页面默认展示的是没数据那个群组那自然什么都看不到。左上角切换群组或者检查 Node-Manager 的群组管理配置。6.4 页面白屏、接口 500现象打开 5000 端口页面空白或者显示 nginx 的 502 Bad Gateway。排查链路502 说明 nginx 起起来了但后端连不上。先去后端看 5001 端口有没有进程lsof -i:5001看一眼。如果进程在再直接 curl 一下 Node-Manager 的健康检查接口比如curl http://127.0.0.1:5001/看返回是不是正常 JSON。如果本机 curl 正常但通过公网访问 502十有八九是安全组没放行 5001 端口。如果页面直接白屏浏览器按 F12 打开开发者工具看 Console 报什么错。常见的是前端静态资源加载路径不对也就是说你访问IP:5000时html 文件加载进来的 js/css 引用的还是带别的端口的绝对路径。这时候检查 nginx 配置里的try_files和 root 路径是否正确。前端资源路径不对跟后端没有半点关系别去重启服务浪费时间。6.5 添加节点或应用扩容后连不上现象链上新增了一个节点或者你部署了多机多群组架构Front 配置了新增节点地址但新节点始终显示不在线。排查链路联盟链节点之间要互相通信PEER 端口30300必须互通SDK 要连新节点channel 端口20200必须放通而且新节点的 sdk 证书也要正确签发。如果是新加入的机构节点它需要在你原有链的群里做“节点准入”操作光把它启动起来是不行的链上共识根本不会把它算作共识节点。这个属于链的运维范畴但浏览器上看到的状态会直接反映出来所以排查问题时也要懂一点链本身的知识。写在最后的一点个人体会我把这个流程跑了不知道多少遍之后最大的感受是搭区块链浏览器本身不复杂难的是理解它为什么要这样分层。很多人一上来就急着下载 WeBASE-Web 解压结果发现页面打不开、数据出不来就开始各种猜。其实你把 Front——Node-Manager——Web 这三层各自负责什么、数据怎么流动想明白了大部分问题自己就能解决。另外如果你只是自己在本地学习一台服务器把节点、数据库、WeBASE 全装了也没问题。但如果是给公司做生产环境我强烈建议至少把 MySQL 和 WeBASE 组件拆到独立机器上节点机单独部署。不是说单机跑不了而是数据量上来之后MySQL 的 I/O 和节点的共识操作会互相抢资源到时候链的出块时延和浏览器的查询速度都会受影响。浏览器这东西平时你可能一周都不打开一次但它就像是链的仪表盘真正的价值在出问题的那一刻——你能在五分钟内定位问题是节点挂了、网络不通还是数据没同步而不是对着日志文件干瞪眼。希望这篇笔记能让你把这条可视化链路一次跑通。