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  }