func (e *Etcd) Load() { mb := e.configMetrics() // Create etcd key-value store and registry. store := store.New() registry := server.NewRegistry(store) // Create stats objects followersStats := server.NewRaftFollowersStats(e.Config.Name) serverStats := server.NewRaftServerStats(e.Config.Name) // Calculate all of our timeouts heartbeatTimeout := time.Duration(e.Config.Peer.HeartbeatTimeout) * time.Millisecond electionTimeout := time.Duration(e.Config.Peer.ElectionTimeout) * time.Millisecond dialTimeout := (3 * heartbeatTimeout) + electionTimeout responseHeaderTimeout := (3 * heartbeatTimeout) + electionTimeout // Create peer server psConfig := server.PeerServerConfig{ Name: e.Config.Name, Scheme: e.Config.PeerTLSInfo().Scheme(), URL: e.Config.Peer.Addr, SnapshotCount: e.Config.SnapshotCount, MaxClusterSize: e.Config.MaxClusterSize, RetryTimes: e.Config.MaxRetryAttempts, RetryInterval: e.Config.RetryInterval, } ps := server.NewPeerServer(psConfig, registry, store, &mb, followersStats, serverStats) psListener := e.configPsListener(psConfig) // Create raft transporter and server raftTransporter := server.NewTransporter(followersStats, serverStats, registry, heartbeatTimeout, dialTimeout, responseHeaderTimeout) if psConfig.Scheme == "https" { raftClientTLSConfig, err := e.Config.PeerTLSInfo().ClientConfig() if err != nil { log.Fatal("raft client TLS error: ", err) } raftTransporter.SetTLSConfig(*raftClientTLSConfig) } raftServer, err := raft.NewServer(e.Config.Name, e.Config.DataDir, raftTransporter, store, ps, "") if err != nil { log.Fatal(err) } raftServer.SetElectionTimeout(electionTimeout) raftServer.SetHeartbeatInterval(heartbeatTimeout) ps.SetRaftServer(raftServer) // Create etcd server s := server.New(e.Config.Name, e.Config.Addr, ps, registry, store, nil) ps.SetServer(s) e.EtcdServer = s e.PeerServer = ps e.PeerServerListener = psListener e.Registry = registry }
// NameFromHostname sets the machine name from the hostname. This is to help // people get started without thinking up a name. func (c *Config) NameFromHostname() { host, err := os.Hostname() if err != nil && host == "" { log.Fatal("Node name required and hostname not set. e.g. '-name=name'") } c.Name = host }
func (e *Etcd) configEtcdListener() net.Listener { var sListener net.Listener var err error if e.Config.EtcdTLSInfo().Scheme() == "https" { etcdServerTLSConfig, err := e.Config.EtcdTLSInfo().ServerConfig() if err != nil { log.Fatal("etcd TLS error: ", err) } sListener, err = server.NewTLSListener(e.Config.BindAddr, etcdServerTLSConfig) if err != nil { log.Fatal("Failed to create TLS etcd listener: ", err) } } else { sListener, err = server.NewListener(e.Config.BindAddr) if err != nil { log.Fatal("Failed to create etcd listener: ", err) } } return sListener }
func (e *Etcd) configPsListener(psConfig server.PeerServerConfig) net.Listener { var psListener net.Listener var err error if psConfig.Scheme == "https" { peerServerTLSConfig, err := e.Config.PeerTLSInfo().ServerConfig() if err != nil { log.Fatal("peer server TLS error: ", err) } psListener, err = server.NewTLSListener(e.Config.Peer.BindAddr, peerServerTLSConfig) if err != nil { log.Fatal("Failed to create peer listener: ", err) } } else { psListener, err = server.NewListener(e.Config.Peer.BindAddr) if err != nil { log.Fatal("Failed to create peer listener: ", err) } } return psListener }
func (e *Etcd) Start(withEtcdServer bool) { e.PeerServer.Start(e.Config.Snapshot, e.Config.Peers) if withEtcdServer { sListener := e.configEtcdListener() go func() { log.Infof("etcd server [name %s, listen on %s, advertised url %s]", e.EtcdServer.Name, sListener.Addr(), e.EtcdServer.URL()) corsInfo, err := ehttp.NewCORSInfo(e.Config.CorsOrigins) if err != nil { log.Fatal("CORS:", err) } sHTTP := &ehttp.CORSHandler{e.EtcdServer.HTTPHandler(), corsInfo} log.Fatal(http.Serve(sListener, sHTTP)) }() } log.Infof("peer server [name %s, listen on %s, advertised url %s]", e.PeerServer.Config.Name, e.PeerServerListener.Addr(), e.PeerServer.Config.URL) // Retrieve CORS configuration corsInfo, err := ehttp.NewCORSInfo(e.Config.CorsOrigins) if err != nil { log.Fatal("CORS:", err) } sHTTP := &ehttp.CORSHandler{e.PeerServer.HTTPHandler(), corsInfo} log.Fatal(http.Serve(e.PeerServerListener, sHTTP)) }
// profile starts CPU profiling. func profile(path string) { f, err := os.Create(path) if err != nil { log.Fatal(err) } pprof.StartCPUProfile(f) c := make(chan os.Signal, 1) signal.Notify(c, os.Interrupt) go func() { sig := <-c log.Infof("captured %v, stopping profiler and exiting..", sig) pprof.StopCPUProfile() os.Exit(1) }() }
func (s *PeerServer) joinCluster(cluster []string) bool { for _, peer := range cluster { if len(peer) == 0 { continue } err := s.joinByPeer(s.raftServer, peer, s.Config.Scheme) if err == nil { log.Debugf("%s joined the cluster via peer %s", s.Config.Name, peer) return true } if _, ok := err.(etcdErr.Error); ok { log.Fatal(err) } log.Warnf("Attempt to join via %s failed: %s", peer, err) } return false }
func main() { // Load configuration. var config = config.New() if err := config.Load(os.Args[1:]); err != nil { fmt.Println(server.Usage() + "\n") fmt.Println(err.Error() + "\n") os.Exit(1) } else if config.ShowVersion { fmt.Println(server.ReleaseVersion) os.Exit(0) } else if config.ShowHelp { fmt.Println(server.Usage() + "\n") os.Exit(0) } // Enable options. if config.VeryVeryVerbose { log.Verbose = true raft.SetLogLevel(raft.Trace) } else if config.VeryVerbose { log.Verbose = true raft.SetLogLevel(raft.Debug) } else if config.Verbose { log.Verbose = true } if config.CPUProfileFile != "" { profile(config.CPUProfileFile) } if config.DataDir == "" { log.Fatal("The data dir was not set and could not be guessed from machine name") } // Create data directory if it doesn't already exist. if err := os.MkdirAll(config.DataDir, 0744); err != nil { log.Fatalf("Unable to create path: %s", err) } // Warn people if they have an info file info := filepath.Join(config.DataDir, "info") if _, err := os.Stat(info); err == nil { log.Warnf("All cached configuration is now ignored. The file %s can be removed.", info) } var mbName string if config.Trace() { mbName = config.MetricsBucketName() runtime.SetBlockProfileRate(1) } mb := metrics.NewBucket(mbName) if config.GraphiteHost != "" { err := mb.Publish(config.GraphiteHost) if err != nil { panic(err) } } // Retrieve CORS configuration corsInfo, err := ehttp.NewCORSInfo(config.CorsOrigins) if err != nil { log.Fatal("CORS:", err) } // Create etcd key-value store and registry. store := store.New() registry := server.NewRegistry(store) // Create stats objects followersStats := server.NewRaftFollowersStats(config.Name) serverStats := server.NewRaftServerStats(config.Name) // Calculate all of our timeouts heartbeatTimeout := time.Duration(config.Peer.HeartbeatTimeout) * time.Millisecond electionTimeout := time.Duration(config.Peer.ElectionTimeout) * time.Millisecond dialTimeout := (3 * heartbeatTimeout) + electionTimeout responseHeaderTimeout := (3 * heartbeatTimeout) + electionTimeout // Create peer server psConfig := server.PeerServerConfig{ Name: config.Name, Scheme: config.PeerTLSInfo().Scheme(), URL: config.Peer.Addr, SnapshotCount: config.SnapshotCount, MaxClusterSize: config.MaxClusterSize, RetryTimes: config.MaxRetryAttempts, RetryInterval: config.RetryInterval, } ps := server.NewPeerServer(psConfig, registry, store, &mb, followersStats, serverStats) var psListener net.Listener if psConfig.Scheme == "https" { peerServerTLSConfig, err := config.PeerTLSInfo().ServerConfig() if err != nil { log.Fatal("peer server TLS error: ", err) } psListener, err = server.NewTLSListener(config.Peer.BindAddr, peerServerTLSConfig) if err != nil { log.Fatal("Failed to create peer listener: ", err) } } else { psListener, err = server.NewListener(config.Peer.BindAddr) if err != nil { log.Fatal("Failed to create peer listener: ", err) } } // Create raft transporter and server raftTransporter := server.NewTransporter(followersStats, serverStats, registry, heartbeatTimeout, dialTimeout, responseHeaderTimeout) if psConfig.Scheme == "https" { raftClientTLSConfig, err := config.PeerTLSInfo().ClientConfig() if err != nil { log.Fatal("raft client TLS error: ", err) } raftTransporter.SetTLSConfig(*raftClientTLSConfig) } raftServer, err := raft.NewServer(config.Name, config.DataDir, raftTransporter, store, ps, "") if err != nil { log.Fatal(err) } raftServer.SetElectionTimeout(electionTimeout) raftServer.SetHeartbeatInterval(heartbeatTimeout) ps.SetRaftServer(raftServer) // Create etcd server s := server.New(config.Name, config.Addr, ps, registry, store, &mb) if config.Trace() { s.EnableTracing() } var sListener net.Listener if config.EtcdTLSInfo().Scheme() == "https" { etcdServerTLSConfig, err := config.EtcdTLSInfo().ServerConfig() if err != nil { log.Fatal("etcd TLS error: ", err) } sListener, err = server.NewTLSListener(config.BindAddr, etcdServerTLSConfig) if err != nil { log.Fatal("Failed to create TLS etcd listener: ", err) } } else { sListener, err = server.NewListener(config.BindAddr) if err != nil { log.Fatal("Failed to create etcd listener: ", err) } } ps.SetServer(s) ps.Start(config.Snapshot, config.Peers) go func() { log.Infof("peer server [name %s, listen on %s, advertised url %s]", ps.Config.Name, psListener.Addr(), ps.Config.URL) sHTTP := &ehttp.CORSHandler{ps.HTTPHandler(), corsInfo} log.Fatal(http.Serve(psListener, sHTTP)) }() log.Infof("etcd server [name %s, listen on %s, advertised url %s]", s.Name, sListener.Addr(), s.URL()) sHTTP := &ehttp.CORSHandler{s.HTTPHandler(), corsInfo} log.Fatal(http.Serve(sListener, sHTTP)) }