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(); } }
/// <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()); }