github.com/angenalZZZ/gofunc@v0.0.0-20210507121333-48ff1be3917b/net/server_unix.go (about)

     1  // +build linux darwin netbsd freebsd openbsd dragonfly
     2  
     3  package net
     4  
     5  import (
     6  	"os"
     7  	"os/signal"
     8  	"runtime"
     9  	"sync"
    10  	"syscall"
    11  	"time"
    12  
    13  	"github.com/angenalZZZ/gofunc/net/internal/netpoll"
    14  )
    15  
    16  type server struct {
    17  	ln              *listener          // all the listeners
    18  	wg              sync.WaitGroup     // event-loop close WaitGroup
    19  	opts            *Options           // options with server
    20  	once            sync.Once          // make sure only signalShutdown once
    21  	cond            *sync.Cond         // shutdown signaler
    22  	codec           ICodec             // codec for TCP stream
    23  	logger          Logger             // customized logger for logging info
    24  	ticktock        chan time.Duration // ticker channel
    25  	mainLoop        *eventloop         // main loop for accepting connections
    26  	eventHandler    EventHandler       // user eventHandler
    27  	subEventLoopSet loadBalancer       // event-loops for handling events
    28  }
    29  
    30  // waitForShutdown waits for a signal to shutdown
    31  func (svr *server) waitForShutdown() {
    32  	svr.cond.L.Lock()
    33  	svr.cond.Wait()
    34  	svr.cond.L.Unlock()
    35  }
    36  
    37  // signalShutdown signals a shutdown an begins server closing
    38  func (svr *server) signalShutdown() {
    39  	svr.once.Do(func() {
    40  		svr.cond.L.Lock()
    41  		svr.cond.Signal()
    42  		svr.cond.L.Unlock()
    43  	})
    44  }
    45  
    46  func (svr *server) startLoops() {
    47  	svr.subEventLoopSet.iterate(func(i int, el *eventloop) bool {
    48  		svr.wg.Add(1)
    49  		go func() {
    50  			el.loopRun()
    51  			svr.wg.Done()
    52  		}()
    53  		return true
    54  	})
    55  }
    56  
    57  func (svr *server) closeLoops() {
    58  	svr.subEventLoopSet.iterate(func(i int, el *eventloop) bool {
    59  		_ = el.poller.Close()
    60  		return true
    61  	})
    62  }
    63  
    64  func (svr *server) startReactors() {
    65  	svr.subEventLoopSet.iterate(func(i int, el *eventloop) bool {
    66  		svr.wg.Add(1)
    67  		go func() {
    68  			svr.activateSubReactor(el)
    69  			svr.wg.Done()
    70  		}()
    71  		return true
    72  	})
    73  }
    74  
    75  func (svr *server) activateLoops(numEventLoop int) error {
    76  	// Create loops locally and bind the listeners.
    77  	for i := 0; i < numEventLoop; i++ {
    78  		if p, err := netpoll.OpenPoller(); err == nil {
    79  			el := &eventloop{
    80  				svr:               svr,
    81  				codec:             svr.codec,
    82  				poller:            p,
    83  				packet:            make([]byte, 0x10000),
    84  				connections:       make(map[int]*conn),
    85  				eventHandler:      svr.eventHandler,
    86  				calibrateCallback: svr.subEventLoopSet.calibrate,
    87  			}
    88  			_ = el.poller.AddRead(svr.ln.fd)
    89  			svr.subEventLoopSet.register(el)
    90  		} else {
    91  			return err
    92  		}
    93  	}
    94  	// Start loops in background
    95  	svr.startLoops()
    96  	return nil
    97  }
    98  
    99  func (svr *server) activateReactors(numEventLoop int) error {
   100  	for i := 0; i < numEventLoop; i++ {
   101  		if p, err := netpoll.OpenPoller(); err == nil {
   102  			el := &eventloop{
   103  				svr:               svr,
   104  				codec:             svr.codec,
   105  				poller:            p,
   106  				packet:            make([]byte, 0x10000),
   107  				connections:       make(map[int]*conn),
   108  				eventHandler:      svr.eventHandler,
   109  				calibrateCallback: svr.subEventLoopSet.calibrate,
   110  			}
   111  			svr.subEventLoopSet.register(el)
   112  		} else {
   113  			return err
   114  		}
   115  	}
   116  
   117  	// Start sub reactors.
   118  	svr.startReactors()
   119  
   120  	if p, err := netpoll.OpenPoller(); err == nil {
   121  		el := &eventloop{
   122  			idx:    -1,
   123  			poller: p,
   124  			svr:    svr,
   125  		}
   126  		_ = el.poller.AddRead(svr.ln.fd)
   127  		svr.mainLoop = el
   128  		// Start main reactor.
   129  		svr.wg.Add(1)
   130  		go func() {
   131  			svr.activateMainReactor()
   132  			svr.wg.Done()
   133  		}()
   134  	} else {
   135  		return err
   136  	}
   137  	return nil
   138  }
   139  
   140  func (svr *server) start(numEventLoop int) error {
   141  	if svr.opts.ReusePort || svr.ln.pconn != nil {
   142  		return svr.activateLoops(numEventLoop)
   143  	}
   144  	return svr.activateReactors(numEventLoop)
   145  }
   146  
   147  func (svr *server) stop() {
   148  	// Wait on a signal for shutdown
   149  	svr.waitForShutdown()
   150  
   151  	// Notify all loops to close by closing all listeners
   152  	svr.subEventLoopSet.iterate(func(i int, el *eventloop) bool {
   153  		sniffErrorAndLog(el.poller.Trigger(func() error {
   154  			return errServerShutdown
   155  		}))
   156  		return true
   157  	})
   158  
   159  	if svr.mainLoop != nil {
   160  		svr.ln.close()
   161  		sniffErrorAndLog(svr.mainLoop.poller.Trigger(func() error {
   162  			return errServerShutdown
   163  		}))
   164  	}
   165  
   166  	// Wait on all loops to complete reading events
   167  	svr.wg.Wait()
   168  
   169  	svr.closeLoops()
   170  
   171  	if svr.mainLoop != nil {
   172  		sniffErrorAndLog(svr.mainLoop.poller.Close())
   173  	}
   174  }
   175  
   176  func serve(eventHandler EventHandler, listener *listener, options *Options) error {
   177  	// Figure out the correct number of loops/goroutines to use.
   178  	numEventLoop := 1
   179  	if options.Multicore {
   180  		numEventLoop = runtime.NumCPU()
   181  	}
   182  	if options.NumEventLoop > 0 {
   183  		numEventLoop = options.NumEventLoop
   184  	}
   185  
   186  	svr := new(server)
   187  	svr.opts = options
   188  	svr.eventHandler = eventHandler
   189  	svr.ln = listener
   190  
   191  	switch options.LB {
   192  	case RoundRobin:
   193  		svr.subEventLoopSet = new(roundRobinEventLoopSet)
   194  	case LeastConnections:
   195  		svr.subEventLoopSet = new(leastConnectionsEventLoopSet)
   196  	case SourceAddrHash:
   197  		svr.subEventLoopSet = new(sourceAddrHashEventLoopSet)
   198  	}
   199  
   200  	svr.cond = sync.NewCond(&sync.Mutex{})
   201  	svr.ticktock = make(chan time.Duration, 1)
   202  	svr.logger = func() Logger {
   203  		if options.Logger == nil {
   204  			return defaultLogger
   205  		}
   206  		return options.Logger
   207  	}()
   208  	svr.codec = func() ICodec {
   209  		if options.Codec == nil {
   210  			return new(BuiltInFrameCodec)
   211  		}
   212  		return options.Codec
   213  	}()
   214  
   215  	server := Server{
   216  		svr:          svr,
   217  		Multicore:    options.Multicore,
   218  		Addr:         listener.lnaddr,
   219  		NumEventLoop: numEventLoop,
   220  		ReusePort:    options.ReusePort,
   221  		TCPKeepAlive: options.TCPKeepAlive,
   222  	}
   223  	switch svr.eventHandler.OnInitComplete(server) {
   224  	case None:
   225  	case Shutdown:
   226  		return nil
   227  	}
   228  	defer svr.eventHandler.OnShutdown(server)
   229  
   230  	shutdown := make(chan os.Signal, 1)
   231  	signal.Notify(shutdown, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
   232  	defer close(shutdown)
   233  
   234  	go func() {
   235  		if <-shutdown == nil {
   236  			return
   237  		}
   238  		svr.signalShutdown()
   239  	}()
   240  
   241  	if err := svr.start(numEventLoop); err != nil {
   242  		svr.closeLoops()
   243  		svr.logger.Printf("gnet server is stoping with error: %v\n", err)
   244  		return err
   245  	}
   246  	defer svr.stop()
   247  
   248  	return nil
   249  }