func main() { buf, err := ioutil.ReadFile("./config.json") if err != nil { log.Fatal(err) } var v Config err = json.Unmarshal(buf, &v) dataDir := v.DataDir os.MkdirAll(dataDir, 0755) if err != nil { log.Fatal(err) } cfg := raft.DefaultConfig() // cfg.EnableSingleNode = true fsm := new(Word) fsm.words = "hahaha" dbStore, err := raftboltdb.NewBoltStore(path.Join(dataDir, "raft_db")) if err != nil { log.Fatal(err) } fileStore, err := raft.NewFileSnapshotStore(dataDir, 1, os.Stdout) if err != nil { log.Fatal(err) } trans, err := raft.NewTCPTransport(v.Bind, nil, 3, 5*time.Second, os.Stdout) if err != nil { log.Fatal(err) } peers := make([]string, 0, 10) peers = raft.AddUniquePeer(peers, "192.168.78.151:12345") peers = raft.AddUniquePeer(peers, "192.168.78.151:12346") peers = raft.AddUniquePeer(peers, "192.168.78.151:12347") peerStore := raft.NewJSONPeers(dataDir, trans) peerStore.SetPeers(peers) r, err := raft.NewRaft(cfg, fsm, dbStore, dbStore, fileStore, peerStore, trans) t := time.NewTicker(time.Duration(1) * time.Second) for { select { case <-t.C: fmt.Println(r.Leader()) } } }
func joinMaster(addr string, peerStore *raft.JSONPeers) []string { type joinRequest struct { Addr string } var buf *bytes.Buffer if data, err := json.Marshal(joinRequest{*peerAddr}); err != nil { log.Fatal("Could not marshal join request:", err) } else { buf = bytes.NewBuffer(data) } client := robusthttp.Client(*networkPassword, true) req, err := http.NewRequest("POST", fmt.Sprintf("https://%s/join", addr), buf) if err != nil { log.Fatal(err) } req.Header.Set("Content-Type", "application/json") if res, err := client.Do(req); err != nil { log.Fatal("Could not send join request:", err) } else if res.StatusCode > 399 { data, _ := ioutil.ReadAll(res.Body) log.Fatal("Join request failed:", string(data)) } else if res.StatusCode > 299 { loc := res.Header.Get("Location") if loc == "" { log.Fatal("Redirect has no Location header") } u, err := url.Parse(loc) if err != nil { log.Fatalf("Could not parse redirection %q: %v", loc, err) } return joinMaster(u.Host, peerStore) } log.Printf("Adding master %q as peer\n", addr) p, err := peerStore.Peers() if err != nil { log.Fatal("Could not read peers:", err) } p = raft.AddUniquePeer(p, addr) peerStore.SetPeers(p) return p }
// setupRaft is used to setup and initialize Raft func (s *Server) setupRaft() error { // If we are in bootstrap mode, enable a single node cluster if s.config.Bootstrap || (s.config.DevMode && !s.config.DevDisableBootstrap) { s.config.RaftConfig.EnableSingleNode = true } // Create the FSM var err error s.fsm, err = NewFSM(s.evalBroker, s.periodicDispatcher, s.config.LogOutput) if err != nil { return err } // Create a transport layer trans := raft.NewNetworkTransport(s.raftLayer, 3, s.config.RaftTimeout, s.config.LogOutput) s.raftTransport = trans // Create the backend raft store for logs and stable storage var log raft.LogStore var stable raft.StableStore var snap raft.SnapshotStore var peers raft.PeerStore if s.config.DevMode { store := raft.NewInmemStore() s.raftInmem = store stable = store log = store snap = raft.NewDiscardSnapshotStore() peers = &raft.StaticPeers{} s.raftPeers = peers } else { // Create the base raft path path := filepath.Join(s.config.DataDir, raftState) if err := ensurePath(path, true); err != nil { return err } // Create the BoltDB backend store, err := raftboltdb.NewBoltStore(filepath.Join(path, "raft.db")) if err != nil { return err } s.raftStore = store stable = store // Wrap the store in a LogCache to improve performance cacheStore, err := raft.NewLogCache(raftLogCacheSize, store) if err != nil { store.Close() return err } log = cacheStore // Create the snapshot store snapshots, err := raft.NewFileSnapshotStore(path, snapshotsRetained, s.config.LogOutput) if err != nil { if s.raftStore != nil { s.raftStore.Close() } return err } snap = snapshots // Setup the peer store s.raftPeers = raft.NewJSONPeers(path, trans) peers = s.raftPeers } // Ensure local host is always included if we are in bootstrap mode if s.config.RaftConfig.EnableSingleNode { p, err := peers.Peers() if err != nil { if s.raftStore != nil { s.raftStore.Close() } return err } if !raft.PeerContained(p, trans.LocalAddr()) { peers.SetPeers(raft.AddUniquePeer(p, trans.LocalAddr())) } } // Make sure we set the LogOutput s.config.RaftConfig.LogOutput = s.config.LogOutput // Setup the leader channel leaderCh := make(chan bool, 1) s.config.RaftConfig.NotifyCh = leaderCh s.leaderCh = leaderCh // Setup the Raft store s.raft, err = raft.NewRaft(s.config.RaftConfig, s.fsm, log, stable, snap, peers, trans) if err != nil { if s.raftStore != nil { s.raftStore.Close() } trans.Close() return err } return nil }
// setupRaft is used to setup and initialize Raft func (s *Server) setupRaft() error { // If we are in bootstrap mode, enable a single node cluster if s.config.Bootstrap { s.config.RaftConfig.EnableSingleNode = true } // Create the base path path := filepath.Join(s.config.DataDir, raftState) if err := ensurePath(path, true); err != nil { return err } // Create the FSM var err error s.fsm, err = NewFSM(s.config.LogOutput) if err != nil { return err } // Create the MDB store for logs and stable storage store, err := raftmdb.NewMDBStoreWithSize(path, raftDBSize) if err != nil { return err } s.raftStore = store // Create the snapshot store snapshots, err := raft.NewFileSnapshotStore(path, snapshotsRetained, s.config.LogOutput) if err != nil { store.Close() return err } // Create a transport layer trans := raft.NewNetworkTransport(s.raftLayer, 3, 10*time.Second, s.config.LogOutput) s.raftTransport = trans // Setup the peer store s.raftPeers = raft.NewJSONPeers(path, trans) // Ensure local host is always included if we are in bootstrap mode if s.config.Bootstrap { peers, err := s.raftPeers.Peers() if err != nil { store.Close() return err } if !raft.PeerContained(peers, trans.LocalAddr()) { s.raftPeers.SetPeers(raft.AddUniquePeer(peers, trans.LocalAddr())) } } // Make sure we set the LogOutput s.config.RaftConfig.LogOutput = s.config.LogOutput // Setup the Raft store s.raft, err = raft.NewRaft(s.config.RaftConfig, s.fsm, store, store, snapshots, s.raftPeers, trans) if err != nil { store.Close() trans.Close() return err } // Start monitoring leadership go s.monitorLeadership() return nil }
// setupRaft is used to setup and initialize Raft func (s *Server) setupRaft() error { // If we are in bootstrap mode, enable a single node cluster if s.config.Bootstrap || s.config.DevMode { s.config.RaftConfig.EnableSingleNode = true } // Create the FSM var err error s.fsm, err = NewFSM(s.tombstoneGC, s.config.LogOutput) if err != nil { return err } // Create a transport layer trans := raft.NewNetworkTransport(s.raftLayer, 3, 10*time.Second, s.config.LogOutput) s.raftTransport = trans var log raft.LogStore var stable raft.StableStore var snap raft.SnapshotStore if s.config.DevMode { store := raft.NewInmemStore() s.raftInmem = store stable = store log = store snap = raft.NewDiscardSnapshotStore() s.raftPeers = &raft.StaticPeers{} } else { // Create the base raft path path := filepath.Join(s.config.DataDir, raftState) if err := ensurePath(path, true); err != nil { return err } // Create the backend raft store for logs and stable storage store, err := raftboltdb.NewBoltStore(filepath.Join(path, "raft.db")) if err != nil { return err } s.raftStore = store stable = store // Wrap the store in a LogCache to improve performance cacheStore, err := raft.NewLogCache(raftLogCacheSize, store) if err != nil { store.Close() return err } log = cacheStore // Create the snapshot store snapshots, err := raft.NewFileSnapshotStore(path, snapshotsRetained, s.config.LogOutput) if err != nil { store.Close() return err } snap = snapshots // Setup the peer store s.raftPeers = raft.NewJSONPeers(path, trans) } // Ensure local host is always included if we are in bootstrap mode if s.config.Bootstrap { peerAddrs, err := s.raftPeers.Peers() if err != nil { if s.raftStore != nil { s.raftStore.Close() } return err } if !raft.PeerContained(peerAddrs, trans.LocalAddr()) { s.raftPeers.SetPeers(raft.AddUniquePeer(peerAddrs, trans.LocalAddr())) } } // Make sure we set the LogOutput s.config.RaftConfig.LogOutput = s.config.LogOutput // Setup the Raft store s.raft, err = raft.NewRaft(s.config.RaftConfig, s.fsm, log, stable, snap, s.raftPeers, trans) if err != nil { if s.raftStore != nil { s.raftStore.Close() } trans.Close() return err } // Start monitoring leadership go s.monitorLeadership() return nil }
func newRaft(a *App) (Cluster, error) { r := new(Raft) if len(a.config.Raft.Addr) == 0 { return nil, nil } peers := make([]string, 0, len(a.config.Raft.Cluster)) r.raftAddr = a.config.Raft.Addr addr, err := net.ResolveTCPAddr("tcp", r.raftAddr) if err != nil { return nil, fmt.Errorf("invalid raft addr format %s, must host:port, err:%v", r.raftAddr, err) } peers = raft.AddUniquePeer(peers, addr.String()) for _, cluster := range a.config.Raft.Cluster { addr, err = net.ResolveTCPAddr("tcp", cluster) if err != nil { return nil, fmt.Errorf("invalid cluster format %s, must host:port, err:%v", cluster, err) } peers = raft.AddUniquePeer(peers, addr.String()) } os.MkdirAll(a.config.Raft.DataDir, 0755) cfg := raft.DefaultConfig() if len(a.config.Raft.LogDir) == 0 { r.log = os.Stdout } else { os.MkdirAll(a.config.Raft.LogDir, 0755) logFile := path.Join(a.config.Raft.LogDir, "raft.log") f, err := os.OpenFile(logFile, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0644) if err != nil { return nil, err } r.log = f cfg.LogOutput = r.log } raftDBPath := path.Join(a.config.Raft.DataDir, "raft_db") r.dbStore, err = raftboltdb.NewBoltStore(raftDBPath) if err != nil { return nil, err } fileStore, err := raft.NewFileSnapshotStore(a.config.Raft.DataDir, 1, r.log) if err != nil { return nil, err } r.trans, err = raft.NewTCPTransport(r.raftAddr, nil, 3, 5*time.Second, r.log) if err != nil { return nil, err } r.peerStore = raft.NewJSONPeers(a.config.Raft.DataDir, r.trans) if a.config.Raft.ClusterState == ClusterStateNew { log.Printf("[INFO] cluster state is new, use new cluster config") r.peerStore.SetPeers(peers) } else { log.Printf("[INFO] cluster state is existing, use previous + new cluster config") ps, err := r.peerStore.Peers() if err != nil { log.Printf("[INFO] get store peers error %v", err) return nil, err } for _, peer := range peers { ps = raft.AddUniquePeer(ps, peer) } r.peerStore.SetPeers(ps) } if peers, _ := r.peerStore.Peers(); len(peers) <= 1 { cfg.EnableSingleNode = true log.Println("[INFO] raft will run in single node mode, may only be used in test") } r.r, err = raft.NewRaft(cfg, a.fsm, r.dbStore, r.dbStore, fileStore, r.peerStore, r.trans) return r, err }
func newPeer(c *Config, fsm *fsm) (*peer, error) { r := &peer{} var err error = nil r.addr = c.Raft.Addr os.MkdirAll(c.Raft.DataDir, 0755) cfg := raft.DefaultConfig() raftDBPath := path.Join(c.Raft.DataDir, "raft_db") r.dbStore, err = raftboltdb.NewBoltStore(raftDBPath) if err != nil { return nil, err } fileStore, err := raft.NewFileSnapshotStore(c.Raft.DataDir, 1, os.Stderr) if err != nil { return nil, err } r.trans, err = raft.NewTCPTransport(r.addr, nil, 3, 5*time.Second, os.Stderr) if err != nil { return nil, err } r.peerStore = raft.NewJSONPeers(c.Raft.DataDir, r.trans) if c.Raft.ClusterState == ClusterStateNew { log.Info("cluster state is new, use new cluster config") r.peerStore.SetPeers(c.Raft.Cluster) } else { log.Info("cluster state is existing, use previous + new cluster config") ps, err := r.peerStore.Peers() if err != nil { log.Error("get store peers error %v", err) return nil, err } for _, peer := range c.Raft.Cluster { ps = raft.AddUniquePeer(ps, peer) } r.peerStore.SetPeers(ps) } if peers, _ := r.peerStore.Peers(); len(peers) <= 1 { cfg.EnableSingleNode = true log.Notice("raft running in single node mode") } r.fsm = fsm r.r, err = raft.NewRaft(cfg, fsm, r.dbStore, r.dbStore, fileStore, r.peerStore, r.trans) if err != nil { return nil, err } // watch for leadership changes go func() { for isLeader := range r.r.LeaderCh() { if isLeader { log.Info("new leader http: %v", c.Addr) r.apply(&action{Cmd: CmdNewLeader, Leader: c.Addr}, applyRetries) } } }() return r, nil }
// NewRaft creates a new Raft instance. raft data is stored under the raft dir in prefix. func NewRaft(c RaftConfig, prefix string, logDir string) (r *Raft, err error) { r = new(Raft) config := raft.DefaultConfig() config.EnableSingleNode = c.Single var logOutput *os.File if logDir != "\n" { logFile := path.Join(logDir, "raft.log") logOutput, err = os.OpenFile(logFile, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0666) if err != nil { Fatal("Could not open raft log file: ", err) } config.LogOutput = logOutput } raftDir := path.Join(prefix, "raft") err = os.MkdirAll(raftDir, 0755) if err != nil { Fatal("Could not create raft storage dir: ", err) } fss, err := raft.NewFileSnapshotStore(raftDir, 1, nil) if err != nil { Error("Could not initialize raft snapshot store: ", err) return } // this should be our externally visible address. If not provided in the // config as 'advertise', we use the address of the listen config. if c.Advertise == nil { c.Advertise = &c.Listen } a, err := net.ResolveTCPAddr("tcp", *c.Advertise) if err != nil { Error("Could not lookup raft advertise address: ", err) return } r.transport, err = raft.NewTCPTransport(c.Listen, a, 3, 10*time.Second, nil) if err != nil { Error("Could not create raft transport: ", err) return } peerStore := raft.NewJSONPeers(raftDir, r.transport) if !c.Single { var peers []net.Addr peers, err = peerStore.Peers() if err != nil { return } for _, peerStr := range c.Peers { peer, err := net.ResolveTCPAddr("tcp", peerStr) if err != nil { Fatal("Bad peer:", err) } if !raft.PeerContained(peers, peer) { peerStore.SetPeers(raft.AddUniquePeer(peers, peer)) } } } else { Warn("Running in single node permitted mode. Only use this for testing!") } r.mdb, err = raftmdb.NewMDBStore(raftDir) if err != nil { Error("Could not create raft store:", err) return } storage, err := NewStorage() if err != nil { Error("Could not create storage:", err) return } r.fsm = &FSM{storage} r.raft, err = raft.NewRaft(config, r.fsm, r.mdb, r.mdb, fss, peerStore, r.transport) if err != nil { Error("Could not initialize raft: ", err) return } return }
// setupRaft is used to setup and initialize Raft func (s *Server) setupRaft() error { // If we are in bootstrap mode, enable a single node cluster if s.config.Bootstrap { s.config.RaftConfig.EnableSingleNode = true } // Create the base state path statePath := filepath.Join(s.config.DataDir, tmpStatePath) if err := os.RemoveAll(statePath); err != nil { return err } if err := ensurePath(statePath, true); err != nil { return err } // Create the FSM var err error s.fsm, err = NewFSM(s.tombstoneGC, statePath, s.config.LogOutput) if err != nil { return err } // Set the maximum raft size based on 32/64bit. Since we are // doing an mmap underneath, we need to limit our use of virtual // address space on 32bit, but don't have to care on 64bit. dbSize := raftDBSize32bit if runtime.GOARCH == "amd64" { dbSize = raftDBSize64bit } // Create the base raft path path := filepath.Join(s.config.DataDir, raftState) if err := ensurePath(path, true); err != nil { return err } // Create the MDB store for logs and stable storage store, err := raftmdb.NewMDBStoreWithSize(path, dbSize) if err != nil { return err } s.raftStore = store // Wrap the store in a LogCache to improve performance cacheStore, err := raft.NewLogCache(raftLogCacheSize, store) if err != nil { store.Close() return err } // Create the snapshot store snapshots, err := raft.NewFileSnapshotStore(path, snapshotsRetained, s.config.LogOutput) if err != nil { store.Close() return err } // Create a transport layer trans := raft.NewNetworkTransport(s.raftLayer, 3, 10*time.Second, s.config.LogOutput) s.raftTransport = trans // Setup the peer store s.raftPeers = raft.NewJSONPeers(path, trans) // Ensure local host is always included if we are in bootstrap mode if s.config.Bootstrap { peers, err := s.raftPeers.Peers() if err != nil { store.Close() return err } if !raft.PeerContained(peers, trans.LocalAddr()) { s.raftPeers.SetPeers(raft.AddUniquePeer(peers, trans.LocalAddr())) } } // Make sure we set the LogOutput s.config.RaftConfig.LogOutput = s.config.LogOutput // Setup the Raft store s.raft, err = raft.NewRaft(s.config.RaftConfig, s.fsm, cacheStore, store, snapshots, s.raftPeers, trans) if err != nil { store.Close() trans.Close() return err } // Start monitoring leadership go s.monitorLeadership() return nil }
// setupRaft is used to setup and initialize Raft func (c *cerebrum) setupRaft() error { // If we are in bootstrap mode, enable a single node cluster if c.config.Bootstrap { c.config.RaftConfig.EnableSingleNode = true } // Create the base state path statePath := filepath.Join(c.config.DataPath, tmpStatePath) if err := os.RemoveAll(statePath); err != nil { return err } if err := os.MkdirAll(filepath.Dir(statePath), 0755); err != nil { return err } // Create the base raft path path := filepath.Join(c.config.DataPath, RaftStateDir) if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil { return err } // Create the backend raft store for logs and stable storage store, err := raftboltdb.NewBoltStore(filepath.Join(path, "raft.db")) if err != nil { return err } c.raftStore = store // Wrap the store in a LogCache to improve performance cacheStore, err := raft.NewLogCache(c.config.LogCacheSize, store) if err != nil { store.Close() return err } // Create the snapshot store snapshots, err := raft.NewFileSnapshotStore(path, c.config.SnapshotsRetained, c.config.LogOutput) if err != nil { store.Close() return err } // Try to bind addr, err := net.ResolveTCPAddr("tcp", c.config.RaftBindAddr) if err != nil { return err } // Start TCP listener listener, err := net.ListenTCP("tcp", addr) if err != nil { return err } // Create connection layer and transport layer := NewRaftLayer(c.dialer, listener.Addr(), c.config.TLSConfig) c.raftTransport = raft.NewNetworkTransport(layer, 3, 10*time.Second, c.config.LogOutput) // Create TLS connection dispatcher dispatcher := yamuxer.NewDispatcher(log.NewLogger(c.config.LogOutput, "dispatcher"), nil) dispatcher.Register(connRaft, layer) dispatcher.Register(connForward, &ForwardingHandler{c.applier, log.NewLogger(c.config.LogOutput, "forwarder")}) // Create TLS connection muxer c.muxer = yamuxer.New(c.context, &yamuxer.Config{ Listener: listener, TLSConfig: c.config.TLSConfig, Deadline: c.config.ConnectionDeadline, LogOutput: c.config.LogOutput, Dispatcher: dispatcher, }) // Setup the peer store c.raftPeers = raft.NewJSONPeers(path, c.raftTransport) // Ensure local host is always included if we are in bootstrap mode if c.config.Bootstrap { peers, err := c.raftPeers.Peers() if err != nil { store.Close() return err } if !raft.PeerContained(peers, c.raftTransport.LocalAddr()) { c.raftPeers.SetPeers(raft.AddUniquePeer(peers, c.raftTransport.LocalAddr())) } } // Make sure we set the LogOutput c.config.RaftConfig.LogOutput = c.config.LogOutput // Setup the Raft store c.raft, err = raft.NewRaft(c.config.RaftConfig, c.fsm, cacheStore, store, snapshots, c.raftPeers, c.raftTransport) if err != nil { store.Close() c.raftTransport.Close() return err } // Setup forwarding and applier c.forwarder = NewForwarder(c.raft, c.dialer, log.NewLogger(c.config.LogOutput, "forwarder")) c.applier = NewApplier(c.raft, c.forwarder, log.NewLogger(c.config.LogOutput, "applier"), c.config.EnqueueTimeout) // // Start monitoring leadership // c.t.Go(func() error { // c.monitorLeadership() // return nil // }) return nil }