func startBenchLookupRegUnreg() { var wg sync.WaitGroup start := time.Now() eachCnt := *size * 10 hostname, _ := os.Hostname() for i := 0; i < *concurrency; i++ { wg.Add(1) go func() { defer wg.Done() lookupPeer := clusterinfo.NewLookupPeer(*lookupAddress, 1024*1024*10, &levellogger.GLogger{}, connectCallback("bench_reg_"+strconv.Itoa(i), hostname)) lookupPeer.Command(nil) // start the connection cmd := nsq.Ping() resp, err := lookupPeer.Command(cmd) if err != nil { log.Printf("ping lookup error : %v\n", err) return } else { log.Printf("ping lookup : %v\n", resp) } cnt := eachCnt for cnt > 0 { cnt-- for _, t := range topics { cmd = nsq.UnRegister(t, strconv.Itoa(i), "") lookupPeer.Command(cmd) cmd = nsq.Register(t, strconv.Itoa(i), "") lookupPeer.Command(cmd) for ch := 0; ch < 10; ch++ { cmd = nsq.UnRegister(t, strconv.Itoa(i), "ch"+strconv.Itoa(ch)) lookupPeer.Command(cmd) cmd = nsq.Register(t, strconv.Itoa(i), "ch"+strconv.Itoa(ch)) lookupPeer.Command(cmd) } } } }() } wg.Wait() runSec := time.Now().Sub(start).Seconds() + 1 log.Printf(" %v request done in %v seconds, qps: %v\n", *concurrency*eachCnt, runSec, float64(*concurrency*eachCnt)/runSec) }
func (n *NsqdServer) lookupLoop(pingInterval time.Duration, metaNotifyChan chan interface{}, optsNotifyChan chan struct{}, exitChan chan int) { var lookupPeers []*clusterinfo.LookupPeer var lookupAddrs []string syncTopicChan := make(chan *clusterinfo.LookupPeer, 2) changed := true hostname, err := os.Hostname() if err != nil { nsqd.NsqLogger().LogErrorf("failed to get hostname - %s", err) os.Exit(1) } // for announcements, lookupd determines the host automatically ticker := time.Tick(pingInterval) allHosts := make([]string, 0) discoveryAddrs := make([]string, 0) discoveryAddrs, _ = n.discoverLookupdNodes(discoveryAddrs) for { if changed { allHosts = allHosts[:0] allHosts = append(allHosts, n.ctx.getOpts().NSQLookupdTCPAddresses...) allHosts = append(allHosts, discoveryAddrs...) nsqd.NsqLogger().Logf("all lookup hosts: %v", allHosts) var tmpPeers []*clusterinfo.LookupPeer var tmpAddrs []string for _, lp := range lookupPeers { if in(lp.String(), allHosts) { tmpPeers = append(tmpPeers, lp) tmpAddrs = append(tmpAddrs, lp.String()) continue } nsqd.NsqLogger().Logf("LOOKUP(%s): removing peer", lp) lp.Close() } lookupPeers = tmpPeers lookupAddrs = tmpAddrs for _, host := range allHosts { if in(host, lookupAddrs) { continue } nsqd.NsqLogger().Logf("LOOKUP(%s): adding peer", host) lookupPeer := clusterinfo.NewLookupPeer(host, n.ctx.getOpts().MaxBodySize, n.ctx.getOpts().Logger, connectCallback(n.ctx, hostname, syncTopicChan, exitChan)) lookupPeer.Command(nil) // start the connection lookupPeers = append(lookupPeers, lookupPeer) lookupAddrs = append(lookupAddrs, host) } n.lookupPeers.Store(lookupPeers) changed = false } select { case <-ticker: // send a heartbeat and read a response (read detects closed conns) for _, lp := range lookupPeers { nsqd.NsqLogger().LogDebugf("LOOKUPD(%s): sending heartbeat", lp) cmd := nsq.Ping() _, err := lp.Command(cmd) if err != nil { nsqd.NsqLogger().Logf("LOOKUPD(%s): ERROR %s - %s", lp, cmd, err) } } discoveryChanged := false discoveryAddrs, discoveryChanged = n.discoverLookupdNodes(discoveryAddrs) if discoveryChanged { changed = true } case val := <-metaNotifyChan: var cmd *nsq.Command var branch string switch val.(type) { case *nsqd.Channel: // notify all nsqlookupds that a new channel exists, or that it's removed // For channel, we just know the full topic name without // knowing the partition branch = "channel" channel := val.(*nsqd.Channel) if channel.Exiting() == true || channel.IsConsumeDisabled() { cmd = nsq.UnRegister(channel.GetTopicName(), strconv.Itoa(channel.GetTopicPart()), channel.GetName()) } else { cmd = nsq.Register(channel.GetTopicName(), strconv.Itoa(channel.GetTopicPart()), channel.GetName()) } case *nsqd.Topic: // notify all nsqlookupds that a new topic exists, or that it's removed branch = "topic" topic := val.(*nsqd.Topic) if topic.Exiting() == true || topic.IsWriteDisabled() { cmd = nsq.UnRegister(topic.GetTopicName(), strconv.Itoa(topic.GetTopicPart()), "") } else { cmd = nsq.Register(topic.GetTopicName(), strconv.Itoa(topic.GetTopicPart()), "") } } errLookupPeers := make([]*clusterinfo.LookupPeer, 0) for _, lp := range lookupPeers { nsqd.NsqLogger().Logf("LOOKUPD(%s): %s %s", lp, branch, cmd) _, err := lp.Command(cmd) if err != nil { nsqd.NsqLogger().LogErrorf("LOOKUPD(%s): ERROR %s - %s", lp, cmd, err) errLookupPeers = append(errLookupPeers, lp) } } if len(errLookupPeers) > 0 { go func() { time.Sleep(time.Second * 3) for _, l := range errLookupPeers { select { case syncTopicChan <- l: case <-exitChan: return default: continue } } }() } case lp := <-syncTopicChan: if in(lp.String(), allHosts) { } else { nsqd.NsqLogger().Logf("LOOKUP(%s): already removed ", lp) lp.Close() continue } nsqd.NsqLogger().Logf("do full sync with lookup: %v", lp) var commands []*nsq.Command // build all the commands first so we exit the lock(s) as fast as possible topicMap := n.ctx.nsqd.GetTopicMapCopy() for _, topicParts := range topicMap { for _, topic := range topicParts { if topic.IsWriteDisabled() { continue } channelMap := topic.GetChannelMapCopy() commands = append(commands, nsq.Register(topic.GetTopicName(), strconv.Itoa(topic.GetTopicPart()), "")) for _, channel := range channelMap { commands = append(commands, nsq.Register(channel.GetTopicName(), strconv.Itoa(channel.GetTopicPart()), channel.GetName())) } } } for index, cmd := range commands { nsqd.NsqLogger().Logf("LOOKUPD(%s): %s", lp, cmd) _, err := lp.Command(cmd) if err != nil { nsqd.NsqLogger().LogErrorf("LOOKUPD(%s): ERROR %s - %s", lp, cmd, err) if in(lp.String(), allHosts) { go func() { time.Sleep(time.Second * 3) select { case syncTopicChan <- lp: case <-exitChan: return default: } }() } break } // avoid too much command once, we need sleep here if index%10 == 0 { time.Sleep(time.Millisecond) } } case <-optsNotifyChan: nsqd.NsqLogger().Logf("got opts notify, check new lookup") changed = true discoveryChanged := false discoveryAddrs, discoveryChanged = n.discoverLookupdNodes(discoveryAddrs) if discoveryChanged { changed = true } case <-exitChan: goto exit } } exit: nsqd.NsqLogger().Logf("LOOKUP: closing") }