问题:
- 使用 cli 容器 invoke 链码的时候是可以正常运作的
- 在 web server 中使用 fabric-sdk-go 来 invoke 链码的时候出现 error registering for TxStatus event: no peers to connect to 的错误
分析:
error registering for TxStatus event: no peers to connect to 说明了 sdk 在提交交易时,无法连接到任何 peer 节点以监听交易事件,首先检查网络因素
使用 docker network inspect network-name
命令检查 Docker 网络配置,可以确保所有相关容器都连接到了正确的网络,这里的图片没有显示完全,实际上所有的 peer 节点、cli、orderer节点都在 fabric-network 这个网络中
还可以通过 docker exec -it docker-name /bin/bash
命令进入对应的容器终端,ping 其他的容器看是否能 ping 通。最后排查了网络的因素
sdk 代码分析:
var (
sdk *fabsdk.FabricSDK // Fabric SDK
configPath = "config.yaml" // 配置文件路径
channelName = "appchannel" // 通道名称
user = "Admin" // 用户
chainCodeName = "fabric-realty" // 链码名称
endpoints = []string{"peer0.tesla.com", "peer0.benz.com"} // 要发送交易的节点
)
func ChannelExecute(fcn string, args [][]byte) (channel.Response, error) {
// 创建客户端,表明在通道的身份
ctx := sdk.ChannelContext(channelName, fabsdk.WithUser(user))
cli, err := channel.New(ctx)
if err != nil {
return channel.Response{}, err
}
// 对区块链账本的写操作(调用了链码的invoke)
resp, err := cli.Execute(channel.Request{
ChaincodeID: chainCodeName,
Fcn: fcn,
Args: args,
}, channel.WithTargetEndpoints(endpoints...))
if err != nil {
return channel.Response{}, err
}
//返回链码执行后的结果
return resp, nil
}
首先创建一个客户端 cli,调用 cli.Execute 函数来调用链码 invoke 函数执行链码,channel.WithTargetEndpoints(endpoints… 参数制定了发送交易的节点,重点就在这个 endPoint 上,在使用 sdk 调用链码时需要设置 endPoint 指定发送的 peer 节点,对应的,在 peer 节点本身也需要设置 peer 节点在网络中的外部端点。
设置 CORE_PEER_GOSSIP_EXTERNALENDPOINT
环境变量来确保 Hyperledger Fabric 网络中的 peer 节点能够正确地进行通信。这个环境变量定义了对等节点在网络中的外部端点,使得其他节点能够找到并与其通信。
具体解决方法:
在 Docker 容器中设置环境变量,也就是在 docker-compose.yaml
文件中为对应的服务定义变量。例如,对于 peer0.benz.com
和 peer0.tesla.com
,在它们各自的 services 的 environment 中添加 CORE_PEER_GOSSIP_EXTERNALENDPOINT
环境变量
services:
peer0.benz.com:
environment:
- CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.benz.com:7051
# 其他环境变量...
peer0.tesla.com:
environment:
- CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.tesla.com:7051
# 其他环境变量...
然后重启 fabric 网络,重新启动节点即可