/// <summary> /// 单独给每一个节点发送心跳信息 和日志信息, /// 如果收到有的节点返回的任期大于当前的任期则节点变为follower /// </summary> /// <returns></returns> private async Task SendHeartbatAsync() { var peers = _configProviders.GetPeersExcludeSelf(_node.GetChannelId()); if (peers.Count() == 0) { return; } //根据提供的节点进行数据访问 PeerStates = PeerStates.Where(p => peers.Select(x => x.Id).Contains(p.Peer.Id)).ToList(); if (PeerStates.Count != peers.Count) { var peersNotInPeerStates = peers.Where(p => !PeerStates.Select(x => x.Peer.Id).Contains(p.Id)).ToList(); peersNotInPeerStates.ForEach(p => { var model = new PeerState(p); PeerStates.Add(new PeerState(p)); }); } var lastlog = _blockDataManager.GetLastBlockEntity(_node.GetChannelId()); var heartbeat = new HeartBeat(); heartbeat.Term = CurrentState.CurrentTerm; heartbeat.LeaderId = CurrentState.Id; heartbeat.Height = lastlog.Header.Number; heartbeat.LogCurrentHash = lastlog.Header.DataHash; heartbeat.LogPreviousHash = lastlog.Header.PreviousHash; heartbeat.LogTerm = lastlog.Header.Term; heartbeat.ChannelId = lastlog.Header.ChannelId; //获取所需要的区块数据 var needBecomeFollower = false; HeartBeatResponse heartResponse = null; foreach (var item in PeerStates) { if (item.HeartBeatTask == null) { item.HeartBeatTask = HeartBeatRequest(item.Peer, heartbeat); } else { _logger.LogInformation($"{item.Peer.Id} {item.HeartBeatTask.IsCompleted}"); //请求完毕就可以重新再发生请求 if (item.HeartBeatTask != null && item.HeartBeatTask.IsCompleted) { try { var rs = await item.HeartBeatTask; //如果返回节点任期大于当前节点任期 则需要变更节点状态 if (rs.Term > CurrentState.CurrentTerm) { needBecomeFollower = true; heartResponse = rs; break; } item.CurrentHash = rs.BlockCurrentHash; item.PreviousHash = rs.BlockPreviousHash; item.Height = rs.Height; item.LogTerm = rs.LogTerm; } catch (Exception ex) { _logger.LogInformation($"心跳请求失败{ex.Message}"); } finally { item.HeartBeatTask = null; } } } } if (needBecomeFollower) { CurrentState.CurrentTerm = heartbeat.Term; BecomeFollower(); } }