github.com/nsqio/nsq@v1.3.0/nsqlookupd/nsqlookupd.go (about)

     1  package nsqlookupd
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"net"
     7  	"os"
     8  	"sync"
     9  
    10  	"github.com/nsqio/nsq/internal/http_api"
    11  	"github.com/nsqio/nsq/internal/protocol"
    12  	"github.com/nsqio/nsq/internal/util"
    13  	"github.com/nsqio/nsq/internal/version"
    14  )
    15  
    16  type NSQLookupd struct {
    17  	sync.RWMutex
    18  	opts         *Options
    19  	tcpListener  net.Listener
    20  	httpListener net.Listener
    21  	tcpServer    *tcpServer
    22  	waitGroup    util.WaitGroupWrapper
    23  	DB           *RegistrationDB
    24  }
    25  
    26  func New(opts *Options) (*NSQLookupd, error) {
    27  	var err error
    28  
    29  	if opts.Logger == nil {
    30  		opts.Logger = log.New(os.Stderr, opts.LogPrefix, log.Ldate|log.Ltime|log.Lmicroseconds)
    31  	}
    32  	l := &NSQLookupd{
    33  		opts: opts,
    34  		DB:   NewRegistrationDB(),
    35  	}
    36  
    37  	l.logf(LOG_INFO, version.String("nsqlookupd"))
    38  
    39  	l.tcpServer = &tcpServer{nsqlookupd: l}
    40  	l.tcpListener, err = net.Listen("tcp", opts.TCPAddress)
    41  	if err != nil {
    42  		return nil, fmt.Errorf("listen (%s) failed - %s", opts.TCPAddress, err)
    43  	}
    44  	l.httpListener, err = net.Listen("tcp", opts.HTTPAddress)
    45  	if err != nil {
    46  		return nil, fmt.Errorf("listen (%s) failed - %s", opts.HTTPAddress, err)
    47  	}
    48  
    49  	return l, nil
    50  }
    51  
    52  // Main starts an instance of nsqlookupd and returns an
    53  // error if there was a problem starting up.
    54  func (l *NSQLookupd) Main() error {
    55  	exitCh := make(chan error)
    56  	var once sync.Once
    57  	exitFunc := func(err error) {
    58  		once.Do(func() {
    59  			if err != nil {
    60  				l.logf(LOG_FATAL, "%s", err)
    61  			}
    62  			exitCh <- err
    63  		})
    64  	}
    65  
    66  	l.waitGroup.Wrap(func() {
    67  		exitFunc(protocol.TCPServer(l.tcpListener, l.tcpServer, l.logf))
    68  	})
    69  	httpServer := newHTTPServer(l)
    70  	l.waitGroup.Wrap(func() {
    71  		exitFunc(http_api.Serve(l.httpListener, httpServer, "HTTP", l.logf))
    72  	})
    73  
    74  	err := <-exitCh
    75  	return err
    76  }
    77  
    78  func (l *NSQLookupd) RealTCPAddr() *net.TCPAddr {
    79  	return l.tcpListener.Addr().(*net.TCPAddr)
    80  }
    81  
    82  func (l *NSQLookupd) RealHTTPAddr() *net.TCPAddr {
    83  	return l.httpListener.Addr().(*net.TCPAddr)
    84  }
    85  
    86  func (l *NSQLookupd) Exit() {
    87  	if l.tcpListener != nil {
    88  		l.tcpListener.Close()
    89  	}
    90  
    91  	if l.tcpServer != nil {
    92  		l.tcpServer.Close()
    93  	}
    94  
    95  	if l.httpListener != nil {
    96  		l.httpListener.Close()
    97  	}
    98  	l.waitGroup.Wait()
    99  }