func setupReplication(c *cli.Context, cluster cluster.Cluster, server *api.Server, discovery discovery.Backend, addr string, leaderTTL time.Duration, tlsConfig *tls.Config) { kvDiscovery, ok := discovery.(*kvdiscovery.Discovery) if !ok { log.Fatal("Leader election is only supported with consul, etcd and zookeeper discovery.") } client := kvDiscovery.Store() p := path.Join(kvDiscovery.Prefix(), leaderElectionPath) candidate := leadership.NewCandidate(client, p, addr, leaderTTL) follower := leadership.NewFollower(client, p) primary := api.NewPrimary(cluster, tlsConfig, &statusHandler{cluster, candidate, follower}, c.GlobalBool("debug"), c.Bool("cors")) replica := api.NewReplica(primary, tlsConfig) go func() { for { run(candidate, server, primary, replica) time.Sleep(defaultRecoverTime) } }() go func() { for { follow(follower, replica, addr) time.Sleep(defaultRecoverTime) } }() server.SetHandler(primary) }
func run(candidate *leadership.Candidate, server *api.Server, primary *mux.Router, replica *api.Replica) { electedCh, errCh := candidate.RunForElection() for { select { case isElected := <-electedCh: if isElected { log.Info("Leader Election: Cluster leadership acquired") server.SetHandler(primary) } else { log.Info("Leader Election: Cluster leadership lost") server.SetHandler(replica) } case err := <-errCh: log.Error(err) return } } }
func run(cl cluster.Cluster, candidate *leadership.Candidate, server *api.Server, primary *mux.Router, replica *api.Replica) { electedCh, errCh := candidate.RunForElection() var watchdog *cluster.Watchdog for { select { case isElected := <-electedCh: if isElected { log.Info("Leader Election: Cluster leadership acquired") watchdog = cluster.NewWatchdog(cl) server.SetHandler(primary) } else { log.Info("Leader Election: Cluster leadership lost") cl.UnregisterEventHandler(watchdog) server.SetHandler(replica) } case err := <-errCh: log.Error(err) return } } }
func setupLeaderElection(server *api.Server, apiHandler http.Handler, discovery discovery.Discovery, addr string, tlsConfig *tls.Config) { kvDiscovery, ok := discovery.(*kvdiscovery.Discovery) if !ok { log.Fatal("Leader election is only supported with consul, etcd and zookeeper discovery.") } client := kvDiscovery.Store() candidate := leadership.NewCandidate(client, leaderElectionPath, addr) follower := leadership.NewFollower(client, leaderElectionPath) proxy := api.NewReverseProxy(tlsConfig) go func() { candidate.RunForElection() electedCh := candidate.ElectedCh() for isElected := range electedCh { if isElected { log.Info("Cluster leadership acquired") server.SetHandler(apiHandler) } else { log.Info("Cluster leadership lost") server.SetHandler(proxy) } } }() go func() { follower.FollowElection() leaderCh := follower.LeaderCh() for leader := range leaderCh { log.Infof("New leader elected: %s", leader) if leader == addr { proxy.SetDestination("") } else { proxy.SetDestination(leader) } } }() }
func setupReplication(c *cli.Context, cluster cluster.Cluster, server *api.Server, discovery discovery.Discovery, addr string, tlsConfig *tls.Config) { kvDiscovery, ok := discovery.(*kvdiscovery.Discovery) if !ok { log.Fatal("Leader election is only supported with consul, etcd and zookeeper discovery.") } client := kvDiscovery.Store() p := path.Join(kvDiscovery.Prefix(), leaderElectionPath) candidate := leadership.NewCandidate(client, p, addr) follower := leadership.NewFollower(client, p) primary := api.NewPrimary(cluster, tlsConfig, &statusHandler{cluster, candidate, follower}, c.Bool("cors")) replica := api.NewReplica(primary, tlsConfig) go func() { candidate.RunForElection() electedCh := candidate.ElectedCh() for isElected := range electedCh { if isElected { log.Info("Cluster leadership acquired") server.SetHandler(primary) } else { log.Info("Cluster leadership lost") server.SetHandler(replica) } } }() go func() { follower.FollowElection() leaderCh := follower.LeaderCh() for leader := range leaderCh { log.Infof("New leader elected: %s", leader) if leader == addr { replica.SetPrimary("") } else { replica.SetPrimary(leader) } } }() server.SetHandler(primary) }