Ejemplo n.º 1
0
        public async Task <HeartBeatResponse> Handle(HeartBeat heartBeat)
        {
            try
            {
                ///接受到了消息  停止计时 等待处理
                _electionTimer.Change(Timeout.Infinite, Timeout.Infinite);
                _logger.LogInformation($"接收到来自{heartBeat.LeaderId} 任期 {heartBeat.Term} 的心跳");
                var rs = new HeartBeatResponse();
                ///获取当前节点最新的区块
                var currentBlock = _blockDataManager.GetLastBlockEntity(_node.GetChannelId());
                //如果区块为0则初始化区块对象
                if (currentBlock == null)
                {
                    currentBlock = new QMBlockSDK.MongoModel.MongoBlock();
                    currentBlock.Header.Number = -1;
                    currentBlock.Header.Term   = -1;
                }
                rs.Term              = CurrentState.CurrentTerm;
                rs.LeaderId          = CurrentState.LeaderId;
                rs.Height            = currentBlock.Header.Number;
                rs.BlockCurrentHash  = currentBlock.Header.DataHash;
                rs.BlockPreviousHash = currentBlock.Header.PreviousHash;
                rs.LeaderId          = CurrentState.LeaderId;
                rs.Success           = false;
                //当前任期大于leader任期 返回当前任期,leaderID和最新日志信息
                if (CurrentState.CurrentTerm > heartBeat.Term)
                {
                    return(rs);
                }
                //任期小于等于leader任期,
                //则返回最新日志,改变自身状态(觉得自身状态和自己最新的日志的任期一致)
                else
                {
                    CurrentState.LeaderId    = heartBeat.LeaderId;
                    CurrentState.CurrentTerm = heartBeat.Term;
                    rs.LeaderId = heartBeat.LeaderId;
                    rs.Success  = true;
                    _logger.LogInformation("请求合法,刷新选举计时器");
                    //同步指定高度的区块
                    await SynchronizedBlockAsync(heartBeat.Height);

                    //接收成功的信息才刷新计时器
                    //ResetElectionTimer();
                    return(rs);
                }
            }
            finally
            {
                //接收成功的信息才刷新计时器
                ResetElectionTimer();
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// 接受来自leader节点的请求时,会接受 同步区块
        /// </summary>
        /// <returns></returns>
        private async Task SynchronizedBlockAsync(long number)
        {
            var lastBlock = _blockDataManager.GetLastBlockEntity(_node.GetChannelId());

            if (lastBlock == null)
            {
                lastBlock = new QMBlockSDK.MongoModel.MongoBlock();
                lastBlock.Header.Number = -1;
                lastBlock.Header.Term   = -1;
            }
            if (lastBlock.Header.Number >= number)
            {
                return;
            }
            var peer = _configProviders.GetPeer(CurrentState.LeaderId);
            //当前block的信息
            var append = new AppendEntries();

            append.ChannelId   = _node.GetChannelId();
            append.Term        = CurrentState.CurrentTerm;
            append.LeaderId    = CurrentState.LeaderId;
            append.BlockHeight = lastBlock.Header.Number;
            append.BlockHash   = lastBlock.Header.DataHash;
            append.BlockTerm   = lastBlock.Header.Term;

            var rs = await peer.Request(append);

            if (!rs.Success)
            {
                _logger.LogWarning("请求区块错误", Newtonsoft.Json.JsonConvert.SerializeObject(append));
                return;
            }
            if (rs.BlockEntity == null)
            {
                return;
            }
            //如果区块不等于空 则 验证区块
            //区块保存
            _blockDataManager.PutOnChainBlockAsync(rs.BlockEntity.ToBlock());
        }