gitee.com/sasukebo/go-micro/v4@v4.7.1/service.go (about) 1 package micro 2 3 import ( 4 "os" 5 "os/signal" 6 rtime "runtime" 7 "strings" 8 "sync" 9 10 "gitee.com/sasukebo/go-micro/v4/client" 11 "gitee.com/sasukebo/go-micro/v4/cmd" 12 "gitee.com/sasukebo/go-micro/v4/debug/handler" 13 "gitee.com/sasukebo/go-micro/v4/debug/stats" 14 "gitee.com/sasukebo/go-micro/v4/debug/trace" 15 "gitee.com/sasukebo/go-micro/v4/logger" 16 plugin "gitee.com/sasukebo/go-micro/v4/plugins" 17 "gitee.com/sasukebo/go-micro/v4/server" 18 "gitee.com/sasukebo/go-micro/v4/store" 19 signalutil "gitee.com/sasukebo/go-micro/v4/util/signal" 20 "gitee.com/sasukebo/go-micro/v4/util/wrapper" 21 ) 22 23 type service struct { 24 opts Options 25 26 once sync.Once 27 } 28 29 func newService(opts ...Option) Service { 30 service := new(service) 31 options := newOptions(opts...) 32 33 // service name 34 serviceName := options.Server.Options().Name 35 36 // wrap client to inject From-Service header on any calls 37 options.Client = wrapper.FromService(serviceName, options.Client) 38 options.Client = wrapper.TraceCall(serviceName, trace.DefaultTracer, options.Client) 39 40 // wrap the server to provide handler stats 41 err := options.Server.Init( 42 server.WrapHandler(wrapper.HandlerStats(stats.DefaultStats)), 43 server.WrapHandler(wrapper.TraceHandler(trace.DefaultTracer)), 44 ) 45 if err != nil { 46 logger.Fatal(err) 47 } 48 49 // set opts 50 service.opts = options 51 52 return service 53 } 54 55 func (s *service) Name() string { 56 return s.opts.Server.Options().Name 57 } 58 59 // Init initialises options. Additionally it calls cmd.Init 60 // which parses command line flags. cmd.Init is only called 61 // on first Init. 62 func (s *service) Init(opts ...Option) { 63 // process options 64 for _, o := range opts { 65 o(&s.opts) 66 } 67 68 s.once.Do(func() { 69 // setup the plugins 70 for _, p := range strings.Split(os.Getenv("MICRO_PLUGIN"), ",") { 71 if len(p) == 0 { 72 continue 73 } 74 75 // load the plugin 76 c, err := plugin.Load(p) 77 if err != nil { 78 logger.Fatal(err) 79 } 80 81 // initialise the plugin 82 if err := plugin.Init(c); err != nil { 83 logger.Fatal(err) 84 } 85 } 86 87 // set cmd name 88 if len(s.opts.Cmd.App().Name) == 0 { 89 s.opts.Cmd.App().Name = s.Server().Options().Name 90 } 91 92 // Initialise the command flags, overriding new service 93 if err := s.opts.Cmd.Init( 94 cmd.Auth(&s.opts.Auth), 95 cmd.Broker(&s.opts.Broker), 96 cmd.Registry(&s.opts.Registry), 97 cmd.Runtime(&s.opts.Runtime), 98 cmd.Transport(&s.opts.Transport), 99 cmd.Client(&s.opts.Client), 100 cmd.Config(&s.opts.Config), 101 cmd.Server(&s.opts.Server), 102 cmd.Store(&s.opts.Store), 103 cmd.Profile(&s.opts.Profile), 104 ); err != nil { 105 logger.Fatal(err) 106 } 107 108 // Explicitly set the table name to the service name 109 name := s.opts.Cmd.App().Name 110 err := s.opts.Store.Init(store.Table(name)) 111 if err != nil { 112 logger.Fatal(err) 113 } 114 }) 115 } 116 117 func (s *service) Options() Options { 118 return s.opts 119 } 120 121 func (s *service) Client() client.Client { 122 return s.opts.Client 123 } 124 125 func (s *service) Server() server.Server { 126 return s.opts.Server 127 } 128 129 func (s *service) String() string { 130 return "micro" 131 } 132 133 func (s *service) Start() error { 134 for _, fn := range s.opts.BeforeStart { 135 if err := fn(); err != nil { 136 return err 137 } 138 } 139 140 if err := s.opts.Server.Start(); err != nil { 141 return err 142 } 143 144 for _, fn := range s.opts.AfterStart { 145 if err := fn(); err != nil { 146 return err 147 } 148 } 149 150 return nil 151 } 152 153 func (s *service) Stop() error { 154 var err error 155 156 for _, fn := range s.opts.BeforeStop { 157 err = fn() 158 } 159 160 if err = s.opts.Server.Stop(); err != nil { 161 return err 162 } 163 164 for _, fn := range s.opts.AfterStop { 165 err = fn() 166 } 167 168 return err 169 } 170 171 func (s *service) Run() (err error) { 172 // exit when help flag is provided 173 for _, v := range os.Args[1:] { 174 if v == "-h" || v == "--help" { 175 os.Exit(0) 176 } 177 } 178 179 // register the debug handler 180 s.opts.Server.Handle( 181 s.opts.Server.NewHandler( 182 handler.NewHandler(s.opts.Client), 183 server.InternalHandler(true), 184 ), 185 ) 186 187 // start the profiler 188 if s.opts.Profile != nil { 189 // to view mutex contention 190 rtime.SetMutexProfileFraction(5) 191 // to view blocking profile 192 rtime.SetBlockProfileRate(1) 193 194 if err = s.opts.Profile.Start(); err != nil { 195 return err 196 } 197 defer func() { 198 err = s.opts.Profile.Stop() 199 if err != nil { 200 logger.Error(err) 201 } 202 }() 203 } 204 205 if logger.V(logger.InfoLevel, logger.DefaultLogger) { 206 logger.Infof("Starting [service] %s", s.Name()) 207 } 208 209 if err = s.Start(); err != nil { 210 return err 211 } 212 213 ch := make(chan os.Signal, 1) 214 if s.opts.Signal { 215 signal.Notify(ch, signalutil.Shutdown()...) 216 } 217 218 select { 219 // wait on kill signal 220 case <-ch: 221 // wait on context cancel 222 case <-s.opts.Context.Done(): 223 } 224 225 return s.Stop() 226 }