FISCO-BCOS / go-sdk

golang SDK of FISCO BCOS
Apache License 2.0
73 stars 58 forks source link

GetBlockByNumber()方法调用出现阻塞 #218

Open chaunsin opened 1 year ago

chaunsin commented 1 year ago

版本

问题

有这样一个场景,我有一个for死循环以指定时间间隔去调用GetBlockByNumber()方法,大概运行一天左右发现这个方法阻塞住了,通过读取代码发现,貌似会存在通道阻塞得问题,我们得代码逻辑片段如下:

for {
        select {
        case <-ctx.Done():
            log.Warnf("[event] %v is exit", lis.Id)
            return nil
        default:
                         // 调用区块高度查询,如果如果有新区块产生则offset+1,没有则睡眠3s等待下次执行
            block, err := s.adapter.RawClient().GetBlockByNumber(ctx, int64(offset), true)
            if err != nil {
                time.Sleep(time.Second * 3)
                log.Warnf("[event] loop GetBlockByNumber(%d) err:%s", offset, err)
                continue
            }

            var blockNum = common.HexToHash(block.Number).Big().Uint64()

            for _, v := range block.Transactions {
                ... 省略校验逻辑与判断
                receipt, err := s.adapter.TransactionReceipt(ctx, hash)
                if err != nil {
                    log.Warnf("[event] TransactionReceipt(%s): %w", hash, err)
                    continue
                }
                ...

                                 // 注意此处log,下文会提及,如果打印了此日志说明已经查询到了区块交易
                log.Infof("[event] listener data {appId:%v,id:%v,srcChainId:%v,listenContract:%v,listenEvent:%v,state:%v,blockNum:%v curBlock:%v curTxId:%v logs:%v}",
                    lis.AppId, lis.LinkId, lis.ChainId, lis.ListenContract, lis.ListenEvent, lis.Status, lis.BlockNum, blockNum, hash, receipt.Logs)
                                 // 发送交易具体业务逻辑
                s.send(ctx, lis, receipt, parse, &_abi, contractAddr)
            }
            log.Infof("[event] block offset %d++", offset)
            offset++
        }
    }

然后我们采集了服务日志

我们自己打印得日志,此日志对应上述代码片段打印得日志,已提取主要内容,以下展示得是GetBlockByNumber()最后几次打印得情况: image

ps: [event] listener data {appId:%v,id:%v,srcChainId:%v,listenContract:%v,listenEvent:%v,state:%v,blockNum:%v curBlock:%v curTxId:%v logs:%v} 日志打印我们并没有查询到,说明没有执行到block.Transactions for循环当中得逻辑

go-sdk 打印得日志:

image 红线上面得日志请求时间和我们自己打印得日志时间能一一对应上,红线下面部分是我们单次调用GetBlockByNumber()方法所产生得日志记录,对应得日志记录如下:

image

ps: 我们区块高度还没达到9999因此报错,这不影响我们所说得问题,从调用结果可以看出我们得链是通得

代码分析

接收响应请求

image

向通道内写入请求响应

image

ok到这我有以下几个疑问?

问题一

我们是根据消息id也就是上述图片当中msg.uuid作为消息读取映射得,在写入数据得时候,那么会不会存在这种情况,当sdk收不到相应得msg.uuid消息时,则图片一中的<-Response.Notify会一直阻塞?

问题二

还是基于问题一,在我们排查sdk日志得时候发现打印了很多decodeChannelMessage error:uncomplete message 错误描述信息,也就是代码channel.go 1127行打印的日志,执行到此处时continue就不会继续执行下去了,那么会不会有这样情况当前decode失败得数据正是我们当前GetBlockByNumber()方法对应得数据?如果是那么就会存在阻塞问题。

image

问题三

msg.uuid链服务端会不会出现重复问题,或者某些规则导致服务端不会返回对应得msg.uuid相应消息,从而造成<-Response.Notify一直阻塞?

ok到这基本上已经把情况说明,请求帮助谢谢!!!

bxq2011hust commented 1 year ago

请使用这个分支的最新代码验证下,https://github.com/FISCO-BCOS/go-sdk/tree/master-FISCO-BCOS-v2 有可能是这个PR解决的问题,对应issue

chaunsin commented 1 year ago

请使用这个分支的最新代码验证下,https://github.com/FISCO-BCOS/go-sdk/tree/master-FISCO-BCOS-v2 有可能是这个PR解决的问题,对应issue

多谢