Пример #1
0
        /// <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();
            }
        }