gitee.com/liuxuezhan/go-micro-v1.18.0@v1.0.0/service.go (about) 1 package micro 2 3 import ( 4 "os" 5 "os/signal" 6 "strings" 7 "sync" 8 "syscall" 9 10 "gitee.com/liuxuezhan/go-micro-v1.18.0/client" 11 "gitee.com/liuxuezhan/go-micro-v1.18.0/config/cmd" 12 "gitee.com/liuxuezhan/go-micro-v1.18.0/debug/profile" 13 "gitee.com/liuxuezhan/go-micro-v1.18.0/debug/profile/pprof" 14 "gitee.com/liuxuezhan/go-micro-v1.18.0/debug/service/handler" 15 "gitee.com/liuxuezhan/go-micro-v1.18.0/plugin" 16 "gitee.com/liuxuezhan/go-micro-v1.18.0/server" 17 "gitee.com/liuxuezhan/go-micro-v1.18.0/util/log" 18 "gitee.com/liuxuezhan/go-micro-v1.18.0/util/wrapper" 19 ) 20 21 type service struct { 22 opts Options 23 24 once sync.Once 25 } 26 27 func newService(opts ...Option) Service { 28 options := newOptions(opts...) 29 30 // service name 31 serviceName := options.Server.Options().Name 32 33 // wrap client to inject From-Service header on any calls 34 options.Client = wrapper.FromService(serviceName, options.Client) 35 36 return &service{ 37 opts: options, 38 } 39 } 40 41 func (s *service) Name() string { 42 return s.opts.Server.Options().Name 43 } 44 45 // Init initialises options. Additionally it calls cmd.Init 46 // which parses command line flags. cmd.Init is only called 47 // on first Init. 48 func (s *service) Init(opts ...Option) { 49 // process options 50 for _, o := range opts { 51 o(&s.opts) 52 } 53 54 s.once.Do(func() { 55 // setup the plugins 56 for _, p := range strings.Split(os.Getenv("MICRO_PLUGIN"), ",") { 57 if len(p) == 0 { 58 continue 59 } 60 61 // load the plugin 62 c, err := plugin.Load(p) 63 if err != nil { 64 log.Fatal(err) 65 } 66 67 // initialise the plugin 68 if err := plugin.Init(c); err != nil { 69 log.Fatal(err) 70 } 71 } 72 73 // Initialise the command flags, overriding new service 74 _ = s.opts.Cmd.Init( 75 cmd.Broker(&s.opts.Broker), 76 cmd.Registry(&s.opts.Registry), 77 cmd.Transport(&s.opts.Transport), 78 cmd.Client(&s.opts.Client), 79 cmd.Server(&s.opts.Server), 80 ) 81 }) 82 } 83 84 func (s *service) Options() Options { 85 return s.opts 86 } 87 88 func (s *service) Client() client.Client { 89 return s.opts.Client 90 } 91 92 func (s *service) Server() server.Server { 93 return s.opts.Server 94 } 95 96 func (s *service) String() string { 97 return "micro" 98 } 99 100 func (s *service) Start() error { 101 for _, fn := range s.opts.BeforeStart { 102 if err := fn(); err != nil { 103 return err 104 } 105 } 106 107 if err := s.opts.Server.Start(); err != nil { 108 return err 109 } 110 111 for _, fn := range s.opts.AfterStart { 112 if err := fn(); err != nil { 113 return err 114 } 115 } 116 117 return nil 118 } 119 120 func (s *service) Stop() error { 121 var gerr error 122 123 for _, fn := range s.opts.BeforeStop { 124 if err := fn(); err != nil { 125 gerr = err 126 } 127 } 128 129 if err := s.opts.Server.Stop(); err != nil { 130 return err 131 } 132 133 for _, fn := range s.opts.AfterStop { 134 if err := fn(); err != nil { 135 gerr = err 136 } 137 } 138 139 return gerr 140 } 141 142 func (s *service) Run() error { 143 // register the debug handler 144 s.opts.Server.Handle( 145 s.opts.Server.NewHandler( 146 handler.DefaultHandler, 147 server.InternalHandler(true), 148 ), 149 ) 150 151 // start the profiler 152 // TODO: set as an option to the service, don't just use pprof 153 if prof := os.Getenv("MICRO_DEBUG_PROFILE"); len(prof) > 0 { 154 service := s.opts.Server.Options().Name 155 version := s.opts.Server.Options().Version 156 id := s.opts.Server.Options().Id 157 profiler := pprof.NewProfile( 158 profile.Name(service + "." + version + "." + id), 159 ) 160 if err := profiler.Start(); err != nil { 161 return err 162 } 163 defer profiler.Stop() 164 } 165 166 if err := s.Start(); err != nil { 167 return err 168 } 169 170 ch := make(chan os.Signal, 1) 171 if s.opts.Signal { 172 signal.Notify(ch, syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT) 173 } 174 175 select { 176 // wait on kill signal 177 case <-ch: 178 // wait on context cancel 179 case <-s.opts.Context.Done(): 180 } 181 182 return s.Stop() 183 }