コード例 #1
0
ファイル: raft_server.go プロジェクト: rramos/influxdb
func (s *RaftServer) joinHandler(w http.ResponseWriter, req *http.Request) {
	if s.raftServer.State() == raft.Leader {
		command := &InfluxJoinCommand{}
		if err := json.NewDecoder(req.Body).Decode(&command); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		log.Debug("ON RAFT LEADER - JOIN: %v", command)
		// during the test suite the join command will sometimes time out.. just retry a few times
		if _, err := s.raftServer.Do(command); err != nil {
			log.Error("Can't process %v: %s", command, err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		server := s.clusterConfig.GetServerByRaftName(command.Name)
		// it's a new server the cluster has never seen, make it a potential
		if server == nil {
			log.Info("Adding new server to the cluster config %s", command.Name)
			clusterServer := cluster.NewClusterServer(command.Name,
				command.ConnectionString,
				command.ProtobufConnectionString,
				nil,
				s.config.ProtobufHeartbeatInterval.Duration)
			addServer := NewAddPotentialServerCommand(clusterServer)
			if _, err := s.raftServer.Do(addServer); err != nil {
				log.Error("Error joining raft server: ", err, command)
				http.Error(w, err.Error(), http.StatusInternalServerError)
				return
			}
		}
		log.Info("Server %s already exist in the cluster config", command.Name)
	} else {
		leader, ok := s.leaderConnectString()
		log.Debug("Non-leader redirecting to: (%v, %v)", leader, ok)
		if ok {
			log.Debug("redirecting to leader to join...")
			http.Redirect(w, req, leader+"/join", http.StatusTemporaryRedirect)
		} else {
			http.Error(w, errors.New("Couldn't find leader of the cluster to join").Error(), http.StatusInternalServerError)
		}
	}
}
コード例 #2
0
ファイル: command.go プロジェクト: hanshenu/influxdb
func (c *InfluxJoinCommand) Apply(server raft.Server) (interface{}, error) {
	err := server.AddPeer(c.Name, c.ConnectionString)
	if err != nil {
		return nil, err
	}

	clusterConfig := server.Context().(*cluster.ClusterConfiguration)

	newServer := clusterConfig.GetServerByRaftName(c.Name)
	// it's a new server the cluster has never seen, make it a potential
	if newServer != nil {
		return nil, fmt.Errorf("Server %s already exist", c.Name)
	}

	log.Info("Adding new server to the cluster config %s", c.Name)
	clusterServer := cluster.NewClusterServer(c.Name,
		c.ConnectionString,
		c.ProtobufConnectionString,
		nil,
		clusterConfig.GetLocalConfiguration())
	clusterConfig.AddPotentialServer(clusterServer)
	return nil, nil
}
コード例 #3
0
ファイル: raft_server.go プロジェクト: rramos/influxdb
func (s *RaftServer) startRaft() error {
	log.Info("Initializing Raft Server: %s %d", s.path, s.port)

	// Initialize and start Raft server.
	transporter := raft.NewHTTPTransporter("/raft")
	var err error
	s.raftServer, err = raft.NewServer(s.name, s.path, transporter, s.clusterConfig, s.clusterConfig, "")
	if err != nil {
		return err
	}

	s.raftServer.LoadSnapshot() // ignore errors

	s.raftServer.AddEventListener(raft.StateChangeEventType, s.raftEventHandler)

	transporter.Install(s.raftServer, s)
	s.raftServer.Start()

	go s.CompactLog()

	if !s.raftServer.IsLogEmpty() {
		log.Info("Recovered from log")
		return nil
	}

	potentialLeaders := s.config.SeedServers

	if len(potentialLeaders) == 0 {
		log.Info("Starting as new Raft leader...")
		name := s.raftServer.Name()
		connectionString := s.connectionString()
		_, err := s.raftServer.Do(&InfluxJoinCommand{
			Name:                     name,
			ConnectionString:         connectionString,
			ProtobufConnectionString: s.config.ProtobufConnectionString(),
		})

		if err != nil {
			log.Error(err)
		}

		protobufConnectString := s.config.ProtobufConnectionString()
		clusterServer := cluster.NewClusterServer(name,
			connectionString,
			protobufConnectString,
			nil,
			s.config.ProtobufHeartbeatInterval.Duration)
		command := NewAddPotentialServerCommand(clusterServer)
		_, err = s.doOrProxyCommand(command, "add_server")
		if err != nil {
			return err
		}
		err = s.CreateRootUser()
		return err
	}

	for {
		for _, leader := range potentialLeaders {
			log.Info("(raft:%s) Attempting to join leader: %s", s.raftServer.Name(), leader)

			if err := s.Join(leader); err == nil {
				log.Info("Joined: %s", leader)
				return nil
			}
		}

		log.Warn("Couldn't join any of the seeds, sleeping and retrying...")
		time.Sleep(100 * time.Millisecond)
	}

	return nil
}