123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330 |
- package mhaya
- import (
- "os"
- "os/signal"
- "sync/atomic"
- "syscall"
- cconst "github.com/mhaya/const"
- ctime "github.com/mhaya/extend/time"
- cutils "github.com/mhaya/extend/utils"
- cfacade "github.com/mhaya/facade"
- clog "github.com/mhaya/logger"
- cactor "github.com/mhaya/net/actor"
- cserializer "github.com/mhaya/net/serializer"
- cprofile "github.com/mhaya/profile"
- )
- const (
- Cluster NodeMode = 1 // 集群模式
- Standalone NodeMode = 2 // 单机模式
- )
- type (
- NodeMode byte
- Application struct {
- cfacade.INode
- isFrontend bool
- nodeMode NodeMode
- startTime ctime.MhayaTime // application start time
- running int32 // is running
- dieChan chan bool // wait for end application
- onShutdownFn []func() // on shutdown execute functions
- components []cfacade.IComponent // all components
- serializer cfacade.ISerializer // serializer
- discovery cfacade.IDiscovery // discovery component
- cluster cfacade.ICluster // cluster component
- actorSystem *cactor.Component // actor system
- netParser cfacade.INetParser // net packet parser
- }
- )
- // NewApp create new application instance
- func NewApp(profileFilePath, nodeId string, isFrontend bool, mode NodeMode) *Application {
- node, err := cprofile.Init(profileFilePath, nodeId)
- if err != nil {
- panic(err)
- }
- return NewAppNode(node, isFrontend, mode)
- }
- func NewAppNode(node cfacade.INode, isFrontend bool, mode NodeMode) *Application {
- // set logger
- clog.SetNodeLogger(node)
- // print version info
- clog.Info(cconst.GetLOGO())
- app := &Application{
- INode: node,
- serializer: cserializer.NewJSON(),
- isFrontend: isFrontend,
- nodeMode: mode,
- startTime: ctime.Now(),
- running: 0,
- dieChan: make(chan bool),
- actorSystem: cactor.New(),
- }
- return app
- }
- func (a *Application) IsFrontend() bool {
- return a.isFrontend
- }
- func (a *Application) NodeMode() NodeMode {
- return a.nodeMode
- }
- func (a *Application) Running() bool {
- return a.running > 0
- }
- func (a *Application) DieChan() chan bool {
- return a.dieChan
- }
- func (a *Application) Register(components ...cfacade.IComponent) {
- if a.Running() {
- return
- }
- for _, c := range components {
- if c == nil || c.Name() == "" {
- clog.Errorf("[component = %T] name is nil", c)
- return
- }
- result := a.Find(c.Name())
- if result != nil {
- clog.Errorf("[component name = %s] is duplicate.", c.Name())
- return
- }
- a.components = append(a.components, c)
- }
- }
- func (a *Application) Find(name string) cfacade.IComponent {
- if name == "" {
- return nil
- }
- for _, component := range a.components {
- if component.Name() == name {
- return component
- }
- }
- return nil
- }
- // Remove component by name
- func (a *Application) Remove(name string) cfacade.IComponent {
- if name == "" {
- return nil
- }
- var removeComponent cfacade.IComponent
- for i := 0; i < len(a.components); i++ {
- if a.components[i].Name() == name {
- removeComponent = a.components[i]
- a.components = append(a.components[:i], a.components[i+1:]...)
- i--
- }
- }
- return removeComponent
- }
- func (a *Application) All() []cfacade.IComponent {
- return a.components
- }
- func (a *Application) OnShutdown(fn ...func()) {
- a.onShutdownFn = append(a.onShutdownFn, fn...)
- }
- // Startup load components before startup
- func (a *Application) Startup() {
- defer func() {
- if r := recover(); r != nil {
- clog.Error(r)
- }
- }()
- if a.Running() {
- clog.Error("Application has running.")
- return
- }
- defer func() {
- clog.Flush()
- }()
- // register actor system
- a.Register(a.actorSystem)
- // add connector component
- if a.netParser != nil {
- for _, connector := range a.netParser.Connectors() {
- a.Register(connector)
- }
- }
- clog.Info("-------------------------------------------------")
- clog.Infof("[nodeId = %s] application is starting...", a.NodeId())
- clog.Infof("[nodeType = %s]", a.NodeType())
- clog.Infof("[pid = %d]", os.Getpid())
- clog.Infof("[startTime = %s]", a.StartTime())
- clog.Infof("[profilePath = %s]", cprofile.Path())
- clog.Infof("[profileName = %s]", cprofile.Name())
- clog.Infof("[env = %s]", cprofile.Env())
- clog.Infof("[debug = %v]", cprofile.Debug())
- clog.Infof("[printLevel = %s]", cprofile.PrintLevel())
- clog.Infof("[logLevel = %s]", clog.DefaultLogger.LogLevel)
- clog.Infof("[stackLevel = %s]", clog.DefaultLogger.StackLevel)
- clog.Infof("[writeFile = %v]", clog.DefaultLogger.EnableWriteFile)
- clog.Infof("[serializer = %s]", a.serializer.Name())
- clog.Info("-------------------------------------------------")
- // component list
- for _, c := range a.components {
- c.Set(a)
- clog.Infof("[component = %s] is added.", c.Name())
- }
- clog.Info("-------------------------------------------------")
- // execute Init()
- for _, c := range a.components {
- clog.Infof("[component = %s] -> OnInit().", c.Name())
- c.Init()
- }
- clog.Info("-------------------------------------------------")
- // execute OnAfterInit()
- for _, c := range a.components {
- clog.Infof("[component = %s] -> OnAfterInit().", c.Name())
- c.OnAfterInit()
- }
- // load net packet parser
- if a.isFrontend {
- if a.netParser == nil {
- clog.Panic("net packet parser is nil.")
- }
- a.netParser.Load(a)
- }
- clog.Info("-------------------------------------------------")
- spendTime := a.startTime.DiffInMillisecond(ctime.Now())
- clog.Infof("[spend time = %dms] application is running.", spendTime)
- clog.Info("-------------------------------------------------")
- // set application is running
- atomic.AddInt32(&a.running, 1)
- sg := make(chan os.Signal, 1)
- signal.Notify(sg, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM)
- select {
- case <-a.dieChan:
- clog.Info("invoke shutdown().")
- case s := <-sg:
- clog.Infof("receive shutdown signal = %v.", s)
- }
- // stop status
- atomic.StoreInt32(&a.running, 0)
- clog.Info("------- application will shutdown -------")
- if a.onShutdownFn != nil {
- for _, f := range a.onShutdownFn {
- cutils.Try(func() {
- f()
- }, func(errString string) {
- clog.Warnf("[onShutdownFn] error = %s", errString)
- })
- }
- }
- //all components in reverse order
- for i := len(a.components) - 1; i >= 0; i-- {
- cutils.Try(func() {
- clog.Infof("[component = %s] -> OnBeforeStop().", a.components[i].Name())
- a.components[i].OnBeforeStop()
- }, func(errString string) {
- clog.Warnf("[component = %s] -> OnBeforeStop(). error = %s", a.components[i].Name(), errString)
- })
- }
- for i := len(a.components) - 1; i >= 0; i-- {
- cutils.Try(func() {
- clog.Infof("[component = %s] -> OnStop().", a.components[i].Name())
- a.components[i].OnStop()
- }, func(errString string) {
- clog.Warnf("[component = %s] -> OnStop(). error = %s", a.components[i].Name(), errString)
- })
- }
- clog.Info("------- application has been shutdown... -------")
- }
- func (a *Application) Shutdown() {
- a.dieChan <- true
- }
- func (a *Application) Serializer() cfacade.ISerializer {
- return a.serializer
- }
- func (a *Application) Discovery() cfacade.IDiscovery {
- return a.discovery
- }
- func (a *Application) Cluster() cfacade.ICluster {
- return a.cluster
- }
- func (a *Application) ActorSystem() cfacade.IActorSystem {
- return a.actorSystem
- }
- func (a *Application) StartTime() string {
- return a.startTime.ToDateTimeFormat()
- }
- func (a *Application) SetSerializer(serializer cfacade.ISerializer) {
- if a.Running() || serializer == nil {
- return
- }
- a.serializer = serializer
- }
- func (a *Application) SetDiscovery(discovery cfacade.IDiscovery) {
- if a.Running() || discovery == nil {
- return
- }
- a.discovery = discovery
- }
- func (a *Application) SetCluster(cluster cfacade.ICluster) {
- if a.Running() || cluster == nil {
- return
- }
- a.cluster = cluster
- }
- func (a *Application) SetNetParser(netParser cfacade.INetParser) {
- if a.Running() || netParser == nil {
- return
- }
- a.netParser = netParser
- }
|