func getWeightedPeers(cluster Cluster) []*api.WeightedPeer { members := cluster.GetMemberlist() var mgrs []*api.WeightedPeer for _, m := range members { mgrs = append(mgrs, &api.WeightedPeer{ Peer: &api.Peer{ NodeID: identity.FormatNodeID(m.RaftID), Addr: m.Addr, }, Weight: 1, }) } return mgrs }
// ResolveAddress returns the address reaching for a given node ID. func (n *Node) ResolveAddress(ctx context.Context, msg *api.ResolveAddressRequest) (*api.ResolveAddressResponse, error) { nodeInfo, err := ca.RemoteNode(ctx) if err != nil { return nil, err } fields := logrus.Fields{ "node.id": nodeInfo.NodeID, "method": "(*Node).ResolveAddress", } if nodeInfo.ForwardedBy != nil { fields["forwarder.id"] = nodeInfo.ForwardedBy.NodeID } log.G(ctx).WithFields(fields).Debugf("") member := n.cluster.GetMember(msg.RaftID) if member == nil { return nil, grpc.Errorf(codes.NotFound, "member %s not found", identity.FormatNodeID(msg.RaftID)) } return &api.ResolveAddressResponse{Addr: member.Addr}, nil }
func (n *Node) sendToMember(members map[uint64]*membership.Member, m raftpb.Message) { defer n.asyncTasks.Done() if n.cluster.IsIDRemoved(m.To) { // Should not send to removed members return } ctx, cancel := context.WithTimeout(n.Ctx, n.sendTimeout) defer cancel() var ( conn *membership.Member ) if toMember, ok := members[m.To]; ok { conn = toMember } else { // If we are being asked to send to a member that's not in // our member list, that could indicate that the current leader // was added while we were offline. Try to resolve its address. n.Config.Logger.Warningf("sending message to an unrecognized member ID %s", identity.FormatNodeID(m.To)) // Choose a random member var ( queryMember *membership.Member id uint64 ) for id, queryMember = range members { if id != n.Config.ID { break } } if queryMember == nil { n.Config.Logger.Error("could not find cluster member to query for leader address") return } resp, err := queryMember.ResolveAddress(ctx, &api.ResolveAddressRequest{RaftID: m.To}) if err != nil { n.Config.Logger.Errorf("could not resolve address of member ID %s: %v", identity.FormatNodeID(m.To), err) return } conn, err = n.ConnectToMember(resp.Addr, n.sendTimeout) if err != nil { n.Config.Logger.Errorf("could connect to member ID %s at %s: %v", identity.FormatNodeID(m.To), resp.Addr, err) return } // The temporary connection is only used for this message. // Eventually, we should catch up and add a long-lived // connection to the member list. defer conn.Conn.Close() } _, err := conn.ProcessRaftMessage(ctx, &api.ProcessRaftMessageRequest{Message: &m}) if err != nil { if grpc.ErrorDesc(err) == ErrMemberRemoved.Error() { atomic.StoreUint32(&n.removed, 1) } if m.Type == raftpb.MsgSnap { n.ReportSnapshot(m.To, raft.SnapshotFailure) } if n.Node == nil { panic("node is nil") } n.ReportUnreachable(m.To) } else if m.Type == raftpb.MsgSnap { n.ReportSnapshot(m.To, raft.SnapshotFinish) } }