//New returns a new instance of the cluster, created using the given Config. func New(config *Config) (*Cluster, error) { c := &Cluster{ Config: config, name: fmt.Sprintf("%d", config.ID), } memberlistConfig := memberlist.DefaultLANConfig() memberlistConfig.Name = c.name memberlistConfig.BindAddr = config.Host memberlistConfig.BindPort = config.Port //TODO Cosmin temporarily disabling any logging from memberlist, we might want to enable it again using logrus? memberlistConfig.LogOutput = ioutil.Discard ml, err := memberlist.Create(memberlistConfig) if err != nil { logger.WithField("error", err).Error("Error when creating the internal memberlist of the cluster") return nil, err } c.memberlist = ml memberlistConfig.Delegate = c memberlistConfig.Conflict = c memberlistConfig.Events = c return c, nil }
func main() { InitLogger(logrus.DebugLevel.String(), "yws1") serfConfig := serf.DefaultConfig() serfConfig.NodeName = "yws1" serfConfig.MemberlistConfig = memberlist.DefaultLANConfig() serfConfig.MemberlistConfig.BindAddr = "127.0.0.1" serfConfig.MemberlistConfig.BindPort = 7373 serfConfig.MemberlistConfig.AdvertiseAddr = "127.0.0.1" serfConfig.MemberlistConfig.AdvertisePort = 5000 eventCh := make(chan serf.Event, 64) serfConfig.EventCh = eventCh serfConfig.LogOutput = ioutil.Discard serfConfig.MemberlistConfig.LogOutput = ioutil.Discard s, err := serf.Create(serfConfig) if err != nil { fmt.Println(err) } go func() { serfShutdownCh := s.ShutdownCh() log.Info("agent: Listen for events") for { select { case e := <-eventCh: log.WithFields(logrus.Fields{ "event": e.String(), }).Debug("agent: Received event") // Log all member events if failed, ok := e.(serf.MemberEvent); ok { for _, member := range failed.Members { log.WithFields(logrus.Fields{ "node": "yang", "member": member.Name, "event": e.EventType(), }).Debug("agent: Member event") } } if e.EventType() == serf.EventQuery { query := e.(*serf.Query) fmt.Println(query) } case <-serfShutdownCh: log.Warn("agent: Serf shutdown detected, quitting") return } } }() fmt.Println(s) wait := make(chan int) <-wait }
func Create() (*Agent, error) { conf := serf.DefaultConfig() conf.Init() conf.NodeName = os.Getenv("HOST") conf.Tags["DOCKER_HOST"] = Os.Getenv("DOCKER_HOST") logOutput := log.StandardLogger().Out // Setup the underlying loggers conf.MemberlistConfig.LogOutput = logOutput conf.LogOutput = logOutput // Create a channel to listen for events from Serf eventCh := make(chan serf.Event, 64) conf.EventCh = eventCh // support only LAN configuration at the moment conf.MemberlistConfig = memberlist.DefaultLANConfig() conf.MemberlistConfig.BindAddr = "0.0.0.0" conf.MemberlistConfig.BindPort = 3388 // Setup the agent agent := &Agent{ conf: conf, eventCh: eventCh, isManager: false, shutdownCh: make(chan struct{}), } return agent, nil }
// DefaultConfig returns a Config struct that contains reasonable defaults // for most of the configurations. func DefaultConfig() *Config { hostname, err := os.Hostname() if err != nil { panic(err) } return &Config{ NodeName: hostname, BroadcastTimeout: 5 * time.Second, EventBuffer: 512, QueryBuffer: 512, LogOutput: os.Stderr, ProtocolVersion: ProtocolVersionMax, ReapInterval: 15 * time.Second, RecentIntentTimeout: 5 * time.Minute, ReconnectInterval: 30 * time.Second, ReconnectTimeout: 24 * time.Hour, QueueDepthWarning: 128, MaxQueueDepth: 4096, TombstoneTimeout: 24 * time.Hour, FlapTimeout: 60 * time.Second, MemberlistConfig: memberlist.DefaultLANConfig(), QueryTimeoutMult: 16, QueryResponseSizeLimit: 1024, QuerySizeLimit: 1024, EnableNameConflictResolution: true, DisableCoordinates: false, } }
// setupAgent is used to create the agent we use func (c *Command) setupAgent(config *Config, logOutput io.Writer) *Agent { bindIP, bindPort, err := config.AddrParts(config.BindAddr) if err != nil { c.Ui.Error(fmt.Sprintf("Invalid bind address: %s", err)) return nil } var advertiseIP string var advertisePort int if config.AdvertiseAddr != "" { advertiseIP, advertisePort, err = config.AddrParts(config.AdvertiseAddr) if err != nil { c.Ui.Error(fmt.Sprintf("Invalid advertise address: %s", err)) return nil } } encryptKey, err := config.EncryptBytes() if err != nil { c.Ui.Error(fmt.Sprintf("Invalid encryption key: %s", err)) return nil } serfConfig := serf.DefaultConfig() switch config.Profile { case "lan": serfConfig.MemberlistConfig = memberlist.DefaultLANConfig() case "wan": serfConfig.MemberlistConfig = memberlist.DefaultWANConfig() case "local": serfConfig.MemberlistConfig = memberlist.DefaultLocalConfig() default: c.Ui.Error(fmt.Sprintf("Unknown profile: %s", config.Profile)) return nil } serfConfig.MemberlistConfig.BindAddr = bindIP serfConfig.MemberlistConfig.BindPort = bindPort serfConfig.MemberlistConfig.AdvertiseAddr = advertiseIP serfConfig.MemberlistConfig.AdvertisePort = advertisePort serfConfig.MemberlistConfig.SecretKey = encryptKey serfConfig.NodeName = config.NodeName serfConfig.Tags = config.Tags serfConfig.SnapshotPath = config.SnapshotPath serfConfig.ProtocolVersion = uint8(config.Protocol) serfConfig.CoalescePeriod = 3 * time.Second serfConfig.QuiescentPeriod = time.Second serfConfig.UserCoalescePeriod = 3 * time.Second serfConfig.UserQuiescentPeriod = time.Second // Start Serf c.Ui.Output("Starting Serf agent...") agent, err := Create(serfConfig, logOutput) if err != nil { c.Ui.Error(fmt.Sprintf("Failed to start the Serf agent: %v", err)) return nil } return agent }
func (nDB *NetworkDB) clusterInit() error { config := memberlist.DefaultLANConfig() config.Name = nDB.config.NodeName config.BindAddr = nDB.config.BindAddr if nDB.config.BindPort != 0 { config.BindPort = nDB.config.BindPort } config.ProtocolVersion = memberlist.ProtocolVersionMax config.Delegate = &delegate{nDB: nDB} config.Events = &eventDelegate{nDB: nDB} config.LogOutput = &logWriter{} var err error if len(nDB.config.Keys) > 0 { for i, key := range nDB.config.Keys { logrus.Debugf("Encryption key %d: %s", i+1, hex.EncodeToString(key)[0:5]) } nDB.keyring, err = memberlist.NewKeyring(nDB.config.Keys, nDB.config.Keys[0]) if err != nil { return err } config.Keyring = nDB.keyring } nDB.networkBroadcasts = &memberlist.TransmitLimitedQueue{ NumNodes: func() int { return len(nDB.nodes) }, RetransmitMult: config.RetransmitMult, } mlist, err := memberlist.Create(config) if err != nil { return fmt.Errorf("failed to create memberlist: %v", err) } nDB.stopCh = make(chan struct{}) nDB.memberlist = mlist nDB.mConfig = config for _, trigger := range []struct { interval time.Duration fn func() }{ {reapInterval, nDB.reapState}, {config.GossipInterval, nDB.gossip}, {config.PushPullInterval, nDB.bulkSyncTables}, } { t := time.NewTicker(trigger.interval) go nDB.triggerFunc(trigger.interval, t.C, nDB.stopCh, trigger.fn) nDB.tickers = append(nDB.tickers, t) } return nil }
func DefaultConfig(name, advertiseAddr string, advertisePort int, seed string, restAPIPort int) *config { c := &config{ seed: seed, restAPIPort: restAPIPort, restAPIProto: "http", } c.MemberlistConfig = memberlist.DefaultLANConfig() c.MemberlistConfig.PushPullInterval = 300 * time.Second c.MemberlistConfig.Name = name c.MemberlistConfig.BindAddr = advertiseAddr c.MemberlistConfig.BindPort = advertisePort c.MemberlistConfig.GossipNodes = c.MemberlistConfig.GossipNodes * 2 return c }
func benchmarkCluster(b *testing.B, num int, timeoutForAllJoins time.Duration, lowestPort int) { startTime := time.Now() var nodes []*memberlist.Memberlist eventC := make(chan memberlist.NodeEvent, num) addr := "127.0.0.1" var firstMemberName string for i := 0; i < num; i++ { c := memberlist.DefaultLANConfig() port := lowestPort + i c.Name = fmt.Sprintf("%s:%d", addr, port) c.BindAddr = addr c.BindPort = port c.ProbeInterval = 20 * time.Millisecond c.ProbeTimeout = 100 * time.Millisecond c.GossipInterval = 20 * time.Millisecond c.PushPullInterval = 200 * time.Millisecond c.LogOutput = ioutil.Discard if i == 0 { c.Events = &memberlist.ChannelEventDelegate{eventC} firstMemberName = c.Name } newMember, err := memberlist.Create(c) if err != nil { log.WithField("error", err).Fatal("Unexpected error when creating the memberlist") } nodes = append(nodes, newMember) defer newMember.Shutdown() if i > 0 { numContacted, err := newMember.Join([]string{firstMemberName}) if numContacted == 0 || err != nil { log.WithField("error", err).Fatal("Unexpected fatal error when node wanted to join the cluster") } } } if convergence(nodes, num, eventC, timeoutForAllJoins) { endTime := time.Now() log.WithField("durationSeconds", endTime.Sub(startTime).Seconds()).Info("Cluster convergence reached") } b.StartTimer() sendMessagesInCluster(nodes, b.N) b.StopTimer() }
// get the default snapd configuration func GetDefaultConfig() *Config { mlCfg := memberlist.DefaultLANConfig() mlCfg.PushPullInterval = defaultPushPullInterval mlCfg.GossipNodes = mlCfg.GossipNodes * 2 return &Config{ Name: getHostname(), Enable: defaultEnable, BindAddr: netutil.GetIP(), BindPort: defaultBindPort, Seed: defaultSeed, MemberlistConfig: mlCfg, RestAPIProto: defaultRestAPIProto, RestAPIPassword: defaultRestAPIPassword, RestAPIPort: defaultRestAPIPort, RestAPIInsecureSkipVerify: defaultRestAPIInsecureSkipVerify, } }
func (t *Tracker) setupMemberlist() (err error) { conf := memberlist.DefaultLANConfig() conf.LogOutput = ioutil.Discard conf.Name = fmt.Sprintf("%s:%s", t.cfg.UUID().FullString(), t.iface) conf.BindAddr = t.iface conf.BindPort = t.port conf.Delegate = newDelegate(t.adport, t.cfg) conf.Events = t.evtHandler t.memberlist, err = memberlist.Create(conf) return }
func main() { fmt.Println("main A") config := memberlist.DefaultLANConfig() config.BindAddr = "192.168.50.25" list, err := memberlist.Create(config) n, err := list.Join([]string{"192.168.50.25"}) if err != nil { panic("Failed to join cluster: " + err.Error()) } log.Println("@n:", n) if err != nil { panic("Failed to create memberlist: " + err.Error()) } for { checkCluster(list) time.Sleep(time.Second) } }
func NewDistributedEventEmitter(cluster []string, bindAddr string) *DistributedEventEmitter { dee := DistributedEventEmitter{} c := memberlist.DefaultLANConfig() c.Name = bindAddr c.BindAddr = bindAddr ml, err := memberlist.Create(c) dee.ml = ml if err != nil { panic("Failed to create memberlist: " + err.Error()) } _, err = dee.ml.Join(cluster) if err != nil { panic("Failed to join cluster: " + err.Error()) } h, err := os.Hostname() if err != nil { panic("Failed to get hostname" + err.Error()) } fmt.Sprintf(dee.nodeId, "%s:%d", h, os.Getpid()) dee.listeners = make(map[string][]func([]byte)) a, err := net.ResolveUDPAddr("udp", mcastAddr) if err != nil { panic("Error converting mcast addr: " + err.Error()) } dee.sub, err = net.ListenMulticastUDP("udp", nil, a) dee.sub.SetReadBuffer(maxDGSize) if err != nil { panic("Failed listen to UDP mcast: " + err.Error()) } go dee.readLoop(dee.sub) return &dee }
// DefaultConfig returns a Config struct that contains reasonable defaults // for most of the configurations. func DefaultConfig() *Config { hostname, err := os.Hostname() if err != nil { panic(err) } return &Config{ NodeName: hostname, BroadcastTimeout: 5 * time.Second, EventBuffer: 512, LogOutput: os.Stderr, ProtocolVersion: ProtocolVersionMax, ReapInterval: 15 * time.Second, RecentIntentBuffer: 128, ReconnectInterval: 30 * time.Second, ReconnectTimeout: 24 * time.Hour, QueueDepthWarning: 128, MaxQueueDepth: 4096, TombstoneTimeout: 24 * time.Hour, MemberlistConfig: memberlist.DefaultLANConfig(), } }
func NewAgent(c *Config) (*Agent, error) { var err error mlConfig := memberlist.DefaultLANConfig() mlConfig.Name = c.Name mlConfig.BindAddr, mlConfig.BindPort, err = parseHostPort(c.BindAddr) if err != nil { return nil, err } if c.AdvertiseAddr != "" { mlConfig.AdvertiseAddr, mlConfig.AdvertisePort, err = parseHostPort(c.AdvertiseAddr) if err != nil { return nil, err } } else { mlConfig.AdvertiseAddr = mlConfig.BindAddr mlConfig.AdvertisePort = mlConfig.BindPort } agent := &Agent{} agent.config = mlConfig mlConfig.Delegate = &Delegate{agent} ml, err := memberlist.Create(mlConfig) if err != nil { log.Fatalf("create memberlist: %s", err.Error()) } agent.memberlist = ml agent.broadcasts = &memberlist.TransmitLimitedQueue{ NumNodes: func() int { return agent.memberlist.NumMembers() }, RetransmitMult: mlConfig.RetransmitMult, } return agent, nil }
// setupAgent is used to create the agent we use func (c *Command) setupAgent(config *Config, logOutput io.Writer) *Agent { bindIP, bindPort, err := config.AddrParts(config.BindAddr) if err != nil { c.Ui.Error(fmt.Sprintf("Invalid bind address: %s", err)) return nil } // Check if we have an interface if iface, _ := config.NetworkInterface(); iface != nil { addrs, err := iface.Addrs() if err != nil { c.Ui.Error(fmt.Sprintf("Failed to get interface addresses: %s", err)) return nil } if len(addrs) == 0 { c.Ui.Error(fmt.Sprintf("Interface '%s' has no addresses", config.Interface)) return nil } // If there is no bind IP, pick an address if bindIP == "0.0.0.0" { found := false for _, a := range addrs { addr, ok := a.(*net.IPNet) if !ok { continue } // Skip self-assigned IPs if addr.IP.IsLinkLocalUnicast() { continue } // Found an IP found = true bindIP = addr.IP.String() c.Ui.Output(fmt.Sprintf("Using interface '%s' address '%s'", config.Interface, bindIP)) // Update the configuration bindAddr := &net.TCPAddr{ IP: net.ParseIP(bindIP), Port: bindPort, } config.BindAddr = bindAddr.String() break } if !found { c.Ui.Error(fmt.Sprintf("Failed to find usable address for interface '%s'", config.Interface)) return nil } } else { // If there is a bind IP, ensure it is available found := false for _, a := range addrs { addr, ok := a.(*net.IPNet) if !ok { continue } if addr.IP.String() == bindIP { found = true break } } if !found { c.Ui.Error(fmt.Sprintf("Interface '%s' has no '%s' address", config.Interface, bindIP)) return nil } } } var advertiseIP string var advertisePort int if config.AdvertiseAddr != "" { advertiseIP, advertisePort, err = config.AddrParts(config.AdvertiseAddr) if err != nil { c.Ui.Error(fmt.Sprintf("Invalid advertise address: %s", err)) return nil } } encryptKey, err := config.EncryptBytes() if err != nil { c.Ui.Error(fmt.Sprintf("Invalid encryption key: %s", err)) return nil } serfConfig := serf.DefaultConfig() switch config.Profile { case "lan": serfConfig.MemberlistConfig = memberlist.DefaultLANConfig() case "wan": serfConfig.MemberlistConfig = memberlist.DefaultWANConfig() case "local": serfConfig.MemberlistConfig = memberlist.DefaultLocalConfig() default: c.Ui.Error(fmt.Sprintf("Unknown profile: %s", config.Profile)) return nil } serfConfig.MemberlistConfig.BindAddr = bindIP serfConfig.MemberlistConfig.BindPort = bindPort serfConfig.MemberlistConfig.AdvertiseAddr = advertiseIP serfConfig.MemberlistConfig.AdvertisePort = advertisePort serfConfig.MemberlistConfig.SecretKey = encryptKey serfConfig.NodeName = config.NodeName serfConfig.Tags = config.Tags serfConfig.SnapshotPath = config.SnapshotPath serfConfig.ProtocolVersion = uint8(config.Protocol) serfConfig.CoalescePeriod = 3 * time.Second serfConfig.QuiescentPeriod = time.Second serfConfig.UserCoalescePeriod = 3 * time.Second serfConfig.UserQuiescentPeriod = time.Second if config.ReconnectInterval != 0 { serfConfig.ReconnectInterval = config.ReconnectInterval } if config.ReconnectTimeout != 0 { serfConfig.ReconnectTimeout = config.ReconnectTimeout } if config.TombstoneTimeout != 0 { serfConfig.TombstoneTimeout = config.TombstoneTimeout } serfConfig.EnableNameConflictResolution = !config.DisableNameResolution if config.KeyringFile != "" { serfConfig.KeyringFile = config.KeyringFile } serfConfig.RejoinAfterLeave = config.RejoinAfterLeave // Start Serf c.Ui.Output("Starting Serf agent...") agent, err := Create(config, serfConfig, logOutput) if err != nil { c.Ui.Error(fmt.Sprintf("Failed to start the Serf agent: %v", err)) return nil } return agent }
func New(cfg *Config) (*tribe, error) { cfg.MemberlistConfig.Name = cfg.Name cfg.MemberlistConfig.BindAddr = cfg.BindAddr cfg.MemberlistConfig.BindPort = cfg.BindPort logger := logger.WithFields(log.Fields{ "port": cfg.MemberlistConfig.BindPort, "addr": cfg.MemberlistConfig.BindAddr, "name": cfg.MemberlistConfig.Name, }) tribe := &tribe{ agreements: map[string]*agreement.Agreement{}, members: map[string]*agreement.Member{}, taskStateResponses: map[string]*taskStateQueryResponse{}, taskStartStopCache: newCache(), msgBuffer: make([]msg, 512), intentBuffer: []msg{}, logger: logger.WithField("_name", cfg.MemberlistConfig.Name), tags: map[string]string{ agreement.RestPort: strconv.Itoa(cfg.RestAPIPort), agreement.RestProtocol: cfg.RestAPIProto, agreement.RestInsecureSkipVerify: cfg.RestAPIInsecureSkipVerify, }, pluginWorkQueue: make(chan worker.PluginRequest, 999), taskWorkQueue: make(chan worker.TaskRequest, 999), workerQuitChan: make(chan struct{}), workerWaitGroup: &sync.WaitGroup{}, config: cfg, EventManager: gomit.NewEventController(), } tribe.broadcasts = &memberlist.TransmitLimitedQueue{ NumNodes: func() int { return len(tribe.memberlist.Members()) }, RetransmitMult: memberlist.DefaultLANConfig().RetransmitMult, } //configure delegates cfg.MemberlistConfig.Delegate = &delegate{tribe: tribe} cfg.MemberlistConfig.Events = &memberDelegate{tribe: tribe} ml, err := memberlist.Create(cfg.MemberlistConfig) if err != nil { logger.Error(err) return nil, err } tribe.memberlist = ml if cfg.Seed != "" { _, err := ml.Join([]string{cfg.Seed}) if err != nil { logger.WithFields(log.Fields{ "seed": cfg.Seed, }).Error(errMemberlistJoin) return nil, errMemberlistJoin } logger.WithFields(log.Fields{ "seed": cfg.Seed, }).Infoln("tribe started") return tribe, nil } logger.WithFields(log.Fields{ "seed": "none", }).Infoln("tribe started") return tribe, nil }
// DefaultConfig provides a basic configuration based on memberlist.DefaultLANConfig() func DefaultConfig() Config { return Config{memberlist.DefaultLANConfig()} }
// setupAgent is used to create the agent we use func (a *AgentCommand) setupSerf(config *Config) *serf.Serf { bindIP, bindPort, err := config.AddrParts(config.BindAddr) if err != nil { a.Ui.Error(fmt.Sprintf("Invalid bind address: %s", err)) return nil } // Check if we have an interface if iface, _ := config.NetworkInterface(); iface != nil { addrs, err := iface.Addrs() if err != nil { a.Ui.Error(fmt.Sprintf("Failed to get interface addresses: %s", err)) return nil } if len(addrs) == 0 { a.Ui.Error(fmt.Sprintf("Interface '%s' has no addresses", config.Interface)) return nil } // If there is no bind IP, pick an address if bindIP == "0.0.0.0" { found := false for _, ad := range addrs { var addrIP net.IP if runtime.GOOS == "windows" { // Waiting for https://github.com/golang/go/issues/5395 to use IPNet only addr, ok := ad.(*net.IPAddr) if !ok { continue } addrIP = addr.IP } else { addr, ok := ad.(*net.IPNet) if !ok { continue } addrIP = addr.IP } // Skip self-assigned IPs if addrIP.IsLinkLocalUnicast() { continue } // Found an IP found = true bindIP = addrIP.String() a.Ui.Output(fmt.Sprintf("Using interface '%s' address '%s'", config.Interface, bindIP)) // Update the configuration bindAddr := &net.TCPAddr{ IP: net.ParseIP(bindIP), Port: bindPort, } config.BindAddr = bindAddr.String() break } if !found { a.Ui.Error(fmt.Sprintf("Failed to find usable address for interface '%s'", config.Interface)) return nil } } else { // If there is a bind IP, ensure it is available found := false for _, a := range addrs { addr, ok := a.(*net.IPNet) if !ok { continue } if addr.IP.String() == bindIP { found = true break } } if !found { a.Ui.Error(fmt.Sprintf("Interface '%s' has no '%s' address", config.Interface, bindIP)) return nil } } } var advertiseIP string var advertisePort int if config.AdvertiseAddr != "" { advertiseIP, advertisePort, err = config.AddrParts(config.AdvertiseAddr) if err != nil { a.Ui.Error(fmt.Sprintf("Invalid advertise address: %s", err)) return nil } } encryptKey, err := config.EncryptBytes() if err != nil { a.Ui.Error(fmt.Sprintf("Invalid encryption key: %s", err)) return nil } serfConfig := serf.DefaultConfig() switch config.Profile { case "lan": serfConfig.MemberlistConfig = memberlist.DefaultLANConfig() case "wan": serfConfig.MemberlistConfig = memberlist.DefaultWANConfig() case "local": serfConfig.MemberlistConfig = memberlist.DefaultLocalConfig() default: a.Ui.Error(fmt.Sprintf("Unknown profile: %s", config.Profile)) return nil } serfConfig.MemberlistConfig.BindAddr = bindIP serfConfig.MemberlistConfig.BindPort = bindPort serfConfig.MemberlistConfig.AdvertiseAddr = advertiseIP serfConfig.MemberlistConfig.AdvertisePort = advertisePort serfConfig.MemberlistConfig.SecretKey = encryptKey serfConfig.NodeName = config.NodeName serfConfig.Tags = config.Tags serfConfig.SnapshotPath = config.SnapshotPath serfConfig.CoalescePeriod = 3 * time.Second serfConfig.QuiescentPeriod = time.Second serfConfig.UserCoalescePeriod = 3 * time.Second serfConfig.UserQuiescentPeriod = time.Second if config.ReconnectInterval != 0 { serfConfig.ReconnectInterval = config.ReconnectInterval } if config.ReconnectTimeout != 0 { serfConfig.ReconnectTimeout = config.ReconnectTimeout } if config.TombstoneTimeout != 0 { serfConfig.TombstoneTimeout = config.TombstoneTimeout } serfConfig.EnableNameConflictResolution = !config.DisableNameResolution if config.KeyringFile != "" { serfConfig.KeyringFile = config.KeyringFile } serfConfig.RejoinAfterLeave = config.RejoinAfterLeave // Create a channel to listen for events from Serf a.eventCh = make(chan serf.Event, 64) serfConfig.EventCh = a.eventCh // Start Serf a.Ui.Output("Starting Serf agent...") log.Info("agent: Serf agent starting") serfConfig.LogOutput = ioutil.Discard serfConfig.MemberlistConfig.LogOutput = ioutil.Discard // Create serf first serf, err := serf.Create(serfConfig) if err != nil { a.Ui.Error(err.Error()) log.Error(err) return nil } return serf }
func main() { log.SetFlags(0) log.SetPrefix("gossipchat: ") port := flag.Int("port", 0, "port on which to listen") nick := flag.String("nick", "", "nickname to use on the chat") peersCSL := flag.String("peers", "", "comma separated list of addresses where peers can be found") flag.Parse() if *nick == "" { log.Fatal("you need to provice a -nick") } peers, err := parsePeers(*peersCSL) if err != nil { log.Fatalf("invalid value for flag -peers. %v", err) } var ( msgc <-chan []message memberc <-chan []string chatc = make(chan message, 1) ) delegate, msgc := newDelegate(100, chatc) conf := memberlist.DefaultLANConfig() conf.LogOutput = ioutil.Discard conf.BindPort = *port conf.Name = *nick conf.Delegate = delegate conf.Events, memberc = newEvents() conf.Conflict = newConflicts() conf.PushPullInterval = time.Second mlist, err := memberlist.Create(conf) if err != nil { log.Fatalf("can't create memberlist: %v", err) } log.SetPrefix(mlist.LocalNode().Name + ": ") delegate.queue.NumNodes = mlist.NumMembers count, err := mlist.Join(peers) if err != nil { log.Printf("can't join peers: %v", err) } log.Printf("joined %d peers", count) log.Printf("we are reachable at %q", fmt.Sprintf("%s:%d", mlist.LocalNode().Addr, mlist.LocalNode().Port)) name := mlist.LocalNode().Name ctx, cancel := context.WithCancel(context.Background()) go func() { defer cancel() uichatc, err := runUI(ctx, name, memberc, msgc) if err != nil { log.Printf("can't start UI: %v", err) return } for chatmsg := range uichatc { select { case chatc <- chatmsg: case <-ctx.Done(): return } } log.Printf("stopped UI") }() <-ctx.Done() if err := mlist.Leave(leaveTimeout); err != nil { log.Printf("could not announce leave: %v", err) } if err := mlist.Shutdown(); err != nil { log.Printf("could not shutdown cleanly: %v", err) } }
func benchmarkCluster(b *testing.B, num int, timeoutForAllJoins time.Duration, lowestPort int) { log.WithField("num", b.N).Fatal("Unexpected error when creating the memberlist") startTime := time.Now() var nodes []*memberlist.Memberlist eventC := make(chan memberlist.NodeEvent, num) addr := "127.0.0.1" var firstMemberName string for i := 0; i < num; i++ { c := memberlist.DefaultLANConfig() port := lowestPort + i c.Name = fmt.Sprintf("%s:%d", addr, port) c.BindAddr = addr c.BindPort = port c.ProbeInterval = 20 * time.Millisecond c.ProbeTimeout = 100 * time.Millisecond c.GossipInterval = 20 * time.Millisecond c.PushPullInterval = 200 * time.Millisecond c.LogOutput = ioutil.Discard if i == 0 { c.Events = &memberlist.ChannelEventDelegate{eventC} firstMemberName = c.Name } newMember, err := memberlist.Create(c) if err != nil { log.WithField("error", err).Fatal("Unexpected error when creating the memberlist") } nodes = append(nodes, newMember) defer newMember.Shutdown() if i >= 0 { num, err := newMember.Join([]string{firstMemberName}) if num == 0 || err != nil { log.WithField("error", err).Fatal("Unexpected fatal error when node wanted to join the cluster") } } } breakTimer := time.After(timeoutForAllJoins) numJoins := 0 WAIT: for { select { case e := <-eventC: l := log.WithFields(log.Fields{ "node": *e.Node, "numJoins": numJoins, "numMembers": nodes[0].NumMembers(), }) if e.Event == memberlist.NodeJoin { l.Info("Node join") numJoins++ if numJoins == num { l.Info("All nodes joined") break WAIT } } else { l.Info("Node leave") } case <-breakTimer: break WAIT } } if numJoins != num { log.WithFields(log.Fields{ "joinCounter": numJoins, "num": num, }).Error("Timeout before completing all joins") } convergence := false for !convergence { convergence = true for idx, node := range nodes { numSeenByNode := node.NumMembers() if numSeenByNode != num { log.WithFields(log.Fields{ "index": idx, "expected": num, "actual": numSeenByNode, }).Debug("Wrong number of nodes") convergence = false break } } } endTime := time.Now() if numJoins == num { log.WithField("durationSeconds", endTime.Sub(startTime).Seconds()).Info("Cluster convergence reached") } b.StartTimer() for senderID, node := range nodes { for receiverID, member := range node.Members() { for i := 0; i < b.N; i++ { message := fmt.Sprintf("Hello from %v to %v !", senderID, receiverID) log.WithField("message", message).Debug("SendToTCP") node.SendToTCP(member, []byte(message)) } } } b.StopTimer() }
func (nDB *NetworkDB) clusterInit() error { config := memberlist.DefaultLANConfig() config.Name = nDB.config.NodeName config.BindAddr = nDB.config.BindAddr config.AdvertiseAddr = nDB.config.AdvertiseAddr if nDB.config.BindPort != 0 { config.BindPort = nDB.config.BindPort } config.ProtocolVersion = memberlist.ProtocolVersionMax config.Delegate = &delegate{nDB: nDB} config.Events = &eventDelegate{nDB: nDB} // custom logger that does not add time or date, so they are not // duplicated by logrus config.Logger = log.New(&logWriter{}, "", 0) var err error if len(nDB.config.Keys) > 0 { for i, key := range nDB.config.Keys { logrus.Debugf("Encryption key %d: %s", i+1, hex.EncodeToString(key)[0:5]) } nDB.keyring, err = memberlist.NewKeyring(nDB.config.Keys, nDB.config.Keys[0]) if err != nil { return err } config.Keyring = nDB.keyring } nDB.networkBroadcasts = &memberlist.TransmitLimitedQueue{ NumNodes: func() int { nDB.RLock() num := len(nDB.nodes) nDB.RUnlock() return num }, RetransmitMult: config.RetransmitMult, } nDB.nodeBroadcasts = &memberlist.TransmitLimitedQueue{ NumNodes: func() int { nDB.RLock() num := len(nDB.nodes) nDB.RUnlock() return num }, RetransmitMult: config.RetransmitMult, } mlist, err := memberlist.Create(config) if err != nil { return fmt.Errorf("failed to create memberlist: %v", err) } nDB.stopCh = make(chan struct{}) nDB.memberlist = mlist for _, trigger := range []struct { interval time.Duration fn func() }{ {reapPeriod, nDB.reapState}, {config.GossipInterval, nDB.gossip}, {config.PushPullInterval, nDB.bulkSyncTables}, {retryInterval, nDB.reconnectNode}, {nodeReapPeriod, nDB.reapDeadNode}, } { t := time.NewTicker(trigger.interval) go nDB.triggerFunc(trigger.interval, t.C, nDB.stopCh, trigger.fn) nDB.tickers = append(nDB.tickers, t) } return nil }
// NewClusterBind creates a new Cluster while allowing for // specification of the address/port to bind to, the address/port to // advertize to the other nodes (use zero values for default) as well // as the hostname. (This is useful if your app is running in a Docker // container where it is impossible to figure out the outside IP // addresses and the hostname can be the same). func NewClusterBind(baddr string, bport int, aaddr string, aport int, rpcport int, name string) (*Cluster, error) { c := &Cluster{ rcvChs: make([]chan *Msg, 0), chgNotify: make([]chan bool, 0), dds: make(map[string]*ddEntry), copies: 1, ncache: make(map[*memberlist.Node]*Node), } cfg := memberlist.DefaultLANConfig() cfg.TCPTimeout = 30 * time.Second cfg.SuspicionMult = 6 cfg.PushPullInterval = 15 * time.Second if baddr != "" { cfg.BindAddr = baddr } if bport != 0 { cfg.BindPort = bport } if aaddr != "" { cfg.AdvertiseAddr = aaddr } if aport != 0 { cfg.AdvertisePort = aport } if name != "" { cfg.Name = name } cfg.LogOutput = &logger{} cfg.Delegate, cfg.Events = c, c var err error if c.Memberlist, err = memberlist.Create(cfg); err != nil { return nil, err } md := &nodeMeta{sortBy: startTime.UnixNano()} c.saveMeta(md) if err = c.UpdateNode(updateNodeTO); err != nil { log.Printf("NewClusterBind(): UpdateNode() failed: %v", err) return nil, err } if rpcport == 0 { c.rpcPort = 12354 } else { c.rpcPort = rpcport } c.snd, c.rcv = c.RegisterMsgType() rpc.Register(&ClusterRPC{c}) if c.rpc, err = net.Listen("tcp", fmt.Sprintf("%s:%d", baddr, c.rpcPort)); err != nil { return nil, err } // Serve RPC Requests go func() { for { rpc.Accept(c.rpc) } }() return c, nil }