func TestTombstonedOldNodes(t *testing.T) { opts := NewOptions() opts.Logger = newTestLogger(t) tcpAddr, httpAddr, nsqlookupd := mustStartLookupd(opts) defer nsqlookupd.Exit() lookupdHTTPAddrs := []string{fmt.Sprintf("%s", httpAddr)} topicName := "inactive_nodes" conn := mustConnectLookupd(t, tcpAddr) defer conn.Close() identify(t, conn, "ip.address", 5000, 5555, "fake-version") OldRegister(topicName, "channel1").WriteTo(conn) _, err := nsq.ReadResponse(conn) equal(t, err, nil) ci := clusterinfo.New(nil, http_api.NewClient(nil)) producers, _ := ci.GetLookupdProducers(lookupdHTTPAddrs) equal(t, len(producers), 1) equal(t, len(producers[0].Topics), 1) equal(t, producers[0].Topics[0].Topic, topicName) equal(t, producers[0].Topics[0].Tombstoned, true) }
func NewHTTPServer(ctx *Context) *httpServer { log := http_api.Log(adminLog) client := http_api.NewClient(ctx.nsqadmin.httpClientTLSConfig) router := httprouter.New() router.HandleMethodNotAllowed = true router.PanicHandler = http_api.LogPanicHandler(adminLog) router.NotFound = http_api.LogNotFoundHandler(adminLog) router.MethodNotAllowed = http_api.LogMethodNotAllowedHandler(adminLog) s := &httpServer{ ctx: ctx, router: router, client: client, ci: clusterinfo.New(ctx.nsqadmin.opts.Logger, client), } router.Handle("GET", "/ping", http_api.Decorate(s.pingHandler, log, http_api.PlainText)) router.Handle("GET", "/", http_api.Decorate(s.indexHandler, log)) router.Handle("GET", "/topics", http_api.Decorate(s.indexHandler, log)) router.Handle("GET", "/topics/:topic", http_api.Decorate(s.indexHandler, log)) router.Handle("GET", "/topics/:topic/:channel", http_api.Decorate(s.indexHandler, log)) router.Handle("GET", "/nodes", http_api.Decorate(s.indexHandler, log)) router.Handle("GET", "/nodes/:node", http_api.Decorate(s.indexHandler, log)) router.Handle("GET", "/counter", http_api.Decorate(s.indexHandler, log)) router.Handle("GET", "/lookup", http_api.Decorate(s.indexHandler, log)) router.Handle("GET", "/statistics", http_api.Decorate(s.indexHandler, log)) router.Handle("GET", "/static/:asset", http_api.Decorate(s.staticAssetHandler, log, http_api.PlainText)) router.Handle("GET", "/fonts/:asset", http_api.Decorate(s.staticAssetHandler, log, http_api.PlainText)) if s.ctx.nsqadmin.opts.ProxyGraphite { proxy := NewSingleHostReverseProxy(ctx.nsqadmin.graphiteURL, 20*time.Second) router.Handler("GET", "/render", proxy) } // v1 endpoints router.Handle("GET", "/api/topics", http_api.Decorate(s.topicsHandler, log, http_api.V1)) router.Handle("GET", "/api/topics/:topic", http_api.Decorate(s.topicHandler, log, http_api.V1)) router.Handle("GET", "/api/coordinators/:node/:topic/:partition", http_api.Decorate(s.coordinatorHandler, log, http_api.V1)) router.Handle("GET", "/api/lookup/nodes", http_api.Decorate(s.lookupNodesHandler, log, http_api.V1)) router.Handle("GET", "/api/topics/:topic/:channel", http_api.Decorate(s.channelHandler, log, http_api.V1)) router.Handle("GET", "/api/nodes", http_api.Decorate(s.nodesHandler, log, http_api.V1)) router.Handle("GET", "/api/nodes/:node", http_api.Decorate(s.nodeHandler, log, http_api.V1)) router.Handle("POST", "/api/topics", http_api.Decorate(s.createTopicChannelHandler, log, http_api.V1)) router.Handle("POST", "/api/topics/:topic", http_api.Decorate(s.topicActionHandler, log, http_api.V1)) router.Handle("POST", "/api/topics/:topic/:channel", http_api.Decorate(s.channelActionHandler, log, http_api.V1)) router.Handle("DELETE", "/api/nodes/:node", http_api.Decorate(s.tombstoneNodeForTopicHandler, log, http_api.V1)) router.Handle("DELETE", "/api/topics/:topic", http_api.Decorate(s.deleteTopicHandler, log, http_api.V1)) router.Handle("DELETE", "/api/topics/:topic/:channel", http_api.Decorate(s.deleteChannelHandler, log, http_api.V1)) router.Handle("GET", "/api/counter", http_api.Decorate(s.counterHandler, log, http_api.V1)) router.Handle("GET", "/api/graphite", http_api.Decorate(s.graphiteHandler, log, http_api.V1)) router.Handle("GET", "/api/statistics", http_api.Decorate(s.statisticsHandler, log, http_api.V1)) router.Handle("GET", "/api/statistics/:filter", http_api.Decorate(s.statisticsHandler, log, http_api.V1)) router.Handle("GET", "/api/cluster/stats", http_api.Decorate(s.clusterStatsHandler, log, http_api.V1)) return s }
func startSimpleTest(msg []byte, batch [][]byte) { // lookup operation cluster := clusterinfo.New(log.New(os.Stderr, "", log.LstdFlags), http_api.NewClient(nil)) ver, err := cluster.GetVersion(*lookupAddress) if err != nil { log.Printf("failed to get lookup version: %v\n", err) } else { log.Printf("get info: %v\n", ver) } tmpList := make([]string, 0) tmpList = append(tmpList, *lookupAddress) currentTopics, err := cluster.GetLookupdTopics(tmpList) if err != nil { log.Printf("failed : %v\n", err) } else { log.Printf("return: %v\n", currentTopics) } if len(currentTopics) == 0 { return } chs, err := cluster.GetLookupdTopicChannels(currentTopics[0], tmpList) if err != nil { log.Printf("failed : %v\n", err) } else { log.Printf("return: %v\n", chs) } allNodes, err := cluster.GetLookupdProducers(tmpList) if err != nil { log.Printf("failed : %v\n", err) } else { log.Printf("return: %v\n", allNodes) } producers, partitionProducers, err := cluster.GetLookupdTopicProducers(currentTopics[0], tmpList) if err != nil { log.Printf("failed : %v\n", err) } else { log.Printf("return: %v, %v\n", producers, partitionProducers) } // nsqd basic tcp operation }
func (t *TopicDiscoverer) syncTopics(addrs []string, pattern string) { newTopics, err := clusterinfo.New(nil, http_api.NewClient(nil)).GetLookupdTopics(addrs) if err != nil { log.Printf("ERROR: could not retrieve topic list: %s", err) } for _, topic := range newTopics { if _, ok := t.topics[topic]; !ok { if !t.allowTopicName(pattern, topic) { log.Println("Skipping topic ", topic, "as it didn't match required pattern:", pattern) continue } logger, err := newConsumerFileLogger(topic, t.cfg) if err != nil { log.Printf("ERROR: couldn't create logger for new topic %s: %s", topic, err) continue } t.topics[topic] = logger go t.startTopicRouter(logger) } } }
func startBenchLookup() { // lookup operation var wg sync.WaitGroup start := time.Now() eachCnt := *size * 10 for j := 0; j < *concurrency; j++ { wg.Add(1) go func() { defer wg.Done() cluster := clusterinfo.New(nil, http_api.NewClient(nil)) tmpList := make([]string, 0) tmpList = append(tmpList, *lookupAddress) currentTopics, err := cluster.GetLookupdTopics(tmpList) if err != nil { log.Printf("failed : %v\n", err) return } else { log.Printf("return: %v\n", currentTopics) } cnt := eachCnt for cnt > 0 { cnt-- for _, t := range currentTopics { _, _, err := cluster.GetLookupdTopicProducers(t, tmpList) if err != nil { log.Printf("failed : %v\n", err) } } time.Sleep(time.Millisecond) } }() } 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 New(opts *Options) *NSQD { dataPath := opts.DataPath if opts.DataPath == "" { cwd, _ := os.Getwd() dataPath = cwd opts.DataPath = dataPath } err := os.MkdirAll(dataPath, 0755) if err != nil { nsqLog.LogErrorf("failed to create directory: %v ", err) os.Exit(1) } DEFAULT_RETENTION_DAYS = int(opts.RetentionDays) nsqLog.Logger = opts.Logger SetRemoteMsgTracer(opts.RemoteTracer) n := &NSQD{ startTime: time.Now(), topicMap: make(map[string]map[int]*Topic), exitChan: make(chan int), MetaNotifyChan: make(chan interface{}), OptsNotificationChan: make(chan struct{}, 1), ci: clusterinfo.New(opts.Logger, http_api.NewClient(nil)), dl: dirlock.New(dataPath), } n.SwapOpts(opts) n.errValue.Store(errStore{}) err = n.dl.Lock() if err != nil { nsqLog.LogErrorf("FATAL: --data-path=%s in use (possibly by another instance of nsqd: %v", dataPath, err) os.Exit(1) } if opts.MaxDeflateLevel < 1 || opts.MaxDeflateLevel > 9 { nsqLog.LogErrorf("FATAL: --max-deflate-level must be [1,9]") os.Exit(1) } if opts.ID < 0 || opts.ID >= MAX_NODE_ID { nsqLog.LogErrorf("FATAL: --worker-id must be [0,%d)", MAX_NODE_ID) os.Exit(1) } nsqLog.Logf("broadcast option: %s, %s", opts.BroadcastAddress, opts.BroadcastInterface) if opts.StatsdPrefix != "" { var port string if opts.ReverseProxyPort != "" { port = opts.ReverseProxyPort } else { _, port, err = net.SplitHostPort(opts.HTTPAddress) if err != nil { nsqLog.LogErrorf("failed to parse HTTP address (%s) - %s", opts.HTTPAddress, err) os.Exit(1) } } statsdHostKey := statsd.HostKey(net.JoinHostPort(opts.BroadcastAddress, port)) prefixWithHost := strings.Replace(opts.StatsdPrefix, "%s", statsdHostKey, -1) if prefixWithHost[len(prefixWithHost)-1] != '.' { prefixWithHost += "." } opts.StatsdPrefix = prefixWithHost nsqLog.Infof("using the stats prefix: %v", opts.StatsdPrefix) } if opts.TLSClientAuthPolicy != "" && opts.TLSRequired == TLSNotRequired { opts.TLSRequired = TLSRequired } return n }
func main() { cfg := nsq.NewConfig() // TODO: remove, deprecated flag.Var(&nsq.ConfigFlag{cfg}, "reader-opt", "(deprecated) use --consumer-opt") flag.Var(&nsq.ConfigFlag{cfg}, "consumer-opt", "option to passthrough to nsq.Consumer (may be given multiple times, http://godoc.org/github.com/absolute8511/go-nsq#Config)") flag.Parse() if *showVersion { fmt.Printf("nsq_to_file v%s\n", version.Binary) return } if *channel == "" { log.Fatal("--channel is required") } var topicsFromNSQLookupd bool if len(lookupdHTTPAddrs) == 0 { log.Fatal("--nsqd-tcp-address or --lookupd-http-address required.") } if *gzipLevel < 1 || *gzipLevel > 9 { log.Fatalf("invalid --gzip-level value (%d), should be 1-9", *gzipLevel) } // TODO: remove, deprecated if hasArg("gzip-compression") { log.Printf("WARNING: --gzip-compression is deprecated in favor of --gzip-level") switch *gzipCompression { case 1: *gzipLevel = gzip.BestSpeed case 2: *gzipLevel = gzip.BestCompression case 3: *gzipLevel = gzip.DefaultCompression default: log.Fatalf("invalid --gzip-compression value (%d), should be 1,2,3", *gzipCompression) } } cfg.UserAgent = fmt.Sprintf("nsq_to_file/%s go-nsq/%s", version.Binary, nsq.VERSION) cfg.MaxInFlight = *maxInFlight discoverer := newTopicDiscoverer(cfg) signal.Notify(discoverer.hupChan, syscall.SIGHUP) signal.Notify(discoverer.termChan, syscall.SIGINT, syscall.SIGTERM) if len(topics) < 1 { if len(lookupdHTTPAddrs) < 1 { log.Fatal("use --topic to list at least one topic to subscribe to or specify at least one --lookupd-http-address to subscribe to all its topics") } topicsFromNSQLookupd = true var err error topics, err = clusterinfo.New(nil, http_api.NewClient(nil)).GetLookupdTopics(lookupdHTTPAddrs) if err != nil { log.Fatalf("ERROR: could not retrieve topic list: %s", err) } } for _, topic := range topics { if !discoverer.allowTopicName(*topicPattern, topic) { log.Println("Skipping topic", topic, "as it didn't match required pattern:", *topicPattern) continue } logger, err := newConsumerFileLogger(topic, cfg) if err != nil { log.Fatalf("ERROR: couldn't create logger for topic %s: %s", topic, err) } discoverer.topics[topic] = logger go discoverer.startTopicRouter(logger) } discoverer.watch(lookupdHTTPAddrs, topicsFromNSQLookupd, *topicPattern) }
func statLoop(interval time.Duration, topic string, channel string, nsqdTCPAddrs []string, lookupdHTTPAddrs []string) { ci := clusterinfo.New(nil, http_api.NewClient(nil)) var o *clusterinfo.ChannelStats for i := 0; !countNum.isSet || countNum.value >= i; i++ { var producers clusterinfo.Producers var err error if len(lookupdHTTPAddrs) != 0 { producers, _, err = ci.GetLookupdTopicProducers(topic, lookupdHTTPAddrs) } else { producers, err = ci.GetNSQDTopicProducers(topic, nsqdHTTPAddrs) } if err != nil { log.Fatalf("ERROR: failed to get topic producers - %s", err) } _, allChannelStats, err := ci.GetNSQDStats(producers, topic, "", false) if err != nil { log.Fatalf("ERROR: failed to get nsqd stats - %s", err) } c, ok := allChannelStats[channel] if !ok { log.Fatalf("ERROR: failed to find channel(%s) in stats metadata for topic(%s)", channel, topic) } if i%25 == 0 { fmt.Printf("%s+%s+%s\n", "------rate------", "----------------depth----------------", "--------------metadata---------------") fmt.Printf("%7s %7s | %7s %7s %7s %5s %5s | %7s %7s %12s %7s\n", "ingress", "egress", "total", "mem", "disk", "inflt", "def", "req", "t-o", "msgs", "clients") } if o == nil { o = c time.Sleep(interval) continue } // TODO: paused fmt.Printf("%7d %7d | %7d %7d %7d %5d %5d | %7d %7d %12d %7d\n", int64(float64(c.MessageCount-o.MessageCount)/interval.Seconds()), int64(float64(c.MessageCount-o.MessageCount-(c.Depth-o.Depth))/interval.Seconds()), c.Depth, c.MemoryDepth, c.BackendDepth, c.InFlightCount, c.DeferredCount, c.RequeueCount, c.TimeoutCount, c.MessageCount, c.ClientCount) o = c time.Sleep(interval) } os.Exit(0) }