|
|
|
package ngs
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"git.noahlan.cn/northlan/ngs/cluster"
|
|
|
|
"git.noahlan.cn/northlan/ngs/component"
|
|
|
|
"git.noahlan.cn/northlan/ngs/internal/env"
|
|
|
|
"git.noahlan.cn/northlan/ngs/internal/log"
|
|
|
|
"git.noahlan.cn/northlan/ngs/internal/runtime"
|
|
|
|
"git.noahlan.cn/northlan/ngs/scheduler"
|
|
|
|
"os"
|
|
|
|
"os/signal"
|
|
|
|
"path/filepath"
|
|
|
|
"strings"
|
|
|
|
"sync/atomic"
|
|
|
|
"syscall"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
var running int32
|
|
|
|
|
|
|
|
// VERSION returns current ngs version
|
|
|
|
var VERSION = "0.1.0"
|
|
|
|
|
|
|
|
var (
|
|
|
|
// app represents the current server process
|
|
|
|
app = &struct {
|
|
|
|
name string // current application name
|
|
|
|
startAt time.Time // startup time
|
|
|
|
}{}
|
|
|
|
)
|
|
|
|
|
|
|
|
// Listen listens on the TCP network address addr
|
|
|
|
// and then calls Serve with handler to handle requests
|
|
|
|
// on incoming connections.
|
|
|
|
func Listen(addr string, opts ...Option) {
|
|
|
|
if atomic.AddInt32(&running, 1) != 1 {
|
|
|
|
log.Println("Ngs has running")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// application initialize
|
|
|
|
app.name = strings.TrimLeft(filepath.Base(os.Args[0]), "/")
|
|
|
|
app.startAt = time.Now()
|
|
|
|
|
|
|
|
// environment initialize
|
|
|
|
if wd, err := os.Getwd(); err != nil {
|
|
|
|
panic(err)
|
|
|
|
} else {
|
|
|
|
env.Wd, _ = filepath.Abs(wd)
|
|
|
|
}
|
|
|
|
|
|
|
|
opt := cluster.Options{
|
|
|
|
Components: &component.Components{},
|
|
|
|
}
|
|
|
|
for _, option := range opts {
|
|
|
|
option(&opt)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Use listen address as client address in non-cluster mode
|
|
|
|
if !opt.IsMaster && opt.AdvertiseAddr == "" && opt.ClientAddr == "" {
|
|
|
|
log.Println("The current server running in singleton mode")
|
|
|
|
opt.ClientAddr = addr
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the retry interval to 3 secondes if doesn't set by user
|
|
|
|
if opt.RetryInterval == 0 {
|
|
|
|
opt.RetryInterval = time.Second * 3
|
|
|
|
}
|
|
|
|
|
|
|
|
node := &cluster.Node{
|
|
|
|
Options: opt,
|
|
|
|
ServiceAddr: addr,
|
|
|
|
}
|
|
|
|
err := node.Startup()
|
|
|
|
if err != nil {
|
|
|
|
log.Fatalf("Node startup failed: %v", err)
|
|
|
|
}
|
|
|
|
runtime.CurrentNode = node
|
|
|
|
|
|
|
|
if node.ClientAddr != "" {
|
|
|
|
log.Println(fmt.Sprintf("Startup *Ngs gate server* %s, client address: %v, service address: %s",
|
|
|
|
app.name, node.ClientAddr, node.ServiceAddr))
|
|
|
|
} else {
|
|
|
|
log.Println(fmt.Sprintf("Startup *Ngs backend server* %s, service address %s",
|
|
|
|
app.name, node.ServiceAddr))
|
|
|
|
}
|
|
|
|
|
|
|
|
go scheduler.Schedule()
|
|
|
|
sg := make(chan os.Signal)
|
|
|
|
signal.Notify(sg, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGKILL, syscall.SIGTERM)
|
|
|
|
|
|
|
|
select {
|
|
|
|
case <-env.Die:
|
|
|
|
log.Println("The app will shutdown in a few seconds")
|
|
|
|
case s := <-sg:
|
|
|
|
log.Println("Ngs server got signal", s)
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Println("Ngs server is stopping...")
|
|
|
|
|
|
|
|
node.Shutdown()
|
|
|
|
runtime.CurrentNode = nil
|
|
|
|
scheduler.Close()
|
|
|
|
atomic.StoreInt32(&running, 0)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Shutdown send a signal to let 'ngs' shutdown itself.
|
|
|
|
func Shutdown() {
|
|
|
|
close(env.Die)
|
|
|
|
}
|