// Start the app on the configured host/port. // // Supports graceful shutdown on 'kill' and 'int' signals. func (app *App) Run() error { if app.vulcandReg != nil { err := app.vulcandReg.Start() if err != nil { return fmt.Errorf("failed to start vulcand registry: err=(%s)", err) } heartbeatCh := make(chan os.Signal, 1) signal.Notify(heartbeatCh, syscall.SIGUSR1) go func() { sig := <-heartbeatCh log.Infof("Got signal %v, canceling vulcand registration", sig) app.vulcandReg.Stop() }() } // listen for a shutdown signal exitCh := make(chan os.Signal, 1) signal.Notify(exitCh, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM) go func() { s := <-exitCh log.Infof("Got signal %v, shutting down", s) if app.vulcandReg != nil { app.vulcandReg.Stop() } manners.Close() }() addr := fmt.Sprintf("%v:%v", app.Config.ListenIP, app.Config.ListenPort) return manners.ListenAndServe(addr, app.router) }
// Start the app on the configured host/port. // // Supports graceful shutdown on 'kill' and 'int' signals. func (app *App) Run() error { // toggle heartbeat on SIGUSR1 go func() { app.heartbeater.Start() heartbeatChan := make(chan os.Signal, 1) signal.Notify(heartbeatChan, syscall.SIGUSR1) for s := range heartbeatChan { log.Infof("Received signal: %v, toggling heartbeat", s) app.heartbeater.Toggle() } }() // listen for a shutdown signal go func() { exitChan := make(chan os.Signal, 1) signal.Notify(exitChan, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM) s := <-exitChan log.Infof("Got shutdown signal: %v", s) manners.Close() }() addr := fmt.Sprintf("%v:%v", app.Config.ListenIP, app.Config.ListenPort) return manners.ListenAndServe(addr, app.router) }
func main() { startup := StartupConfig{} flag.StringVar(&startup.ConfigFile, "config", "/etc/servicegateway.json", "configuration file") flag.StringVar(&startup.DispatchingMode, "dispatch", "path", "dispatching mode ('path' or 'host')") flag.IntVar(&startup.Port, "port", 8080, "HTTP port to listen on") flag.BoolVar(&startup.Debug, "debug", false, "enable to add debug information to each request") flag.StringVar(&startup.ConsulBaseKey, "consul-base", "gateway/ui", "base key name for configuration") flag.StringVar(&startup.UiDir, "ui-dir", "/usr/share/servicegateway", "directory in which UI files can be found") flag.Parse() logger := logging.MustGetLogger("startup") format := logging.MustStringFormatter("%{color}%{time:15:04:05.000} %{module:12s} ▶ %{level:.4s} %{id:03x}%{color:reset} %{message}") backend := logging.NewLogBackend(os.Stderr, "", 0) logging.SetBackend(logging.NewBackendFormatter(backend, format)) logger.Info("Completed startup") cfg := config.Configuration{} data, err := ioutil.ReadFile(startup.ConfigFile) if err != nil { logger.Fatal(err) } err = json.Unmarshal(data, &cfg) if err != nil { logger.Fatal(err) panic(err) } logger.Debug("%s", cfg) consulConfig := api.DefaultConfig() consulConfig.Address = "consul.service.consul:8500" consulConfig.Datacenter = "dev" consulClient, err := api.NewClient(consulConfig) if err != nil { logger.Panic(err) } redisPool := redis.NewPool(func() (redis.Conn, error) { return redis.Dial("tcp", cfg.Redis) }, 8) handler := proxy.NewProxyHandler(logging.MustGetLogger("proxy")) listenAddress := fmt.Sprintf(":%d", startup.Port) done := make(chan bool) go func() { var lastIndex uint64 = 0 var err error dispChan := make(chan dispatcher.Dispatcher) go func() { for disp := range dispChan { logger.Info("starting dispatcher on address %s", listenAddress) manners.ListenAndServe(listenAddress, disp) } }() for { var dispatcher dispatcher.Dispatcher if lastIndex > 0 { time.Sleep(30 * time.Second) } dispatcher, lastIndex, err = buildDispatcher( &startup, &cfg, consulClient, handler, redisPool, logger, lastIndex, ) if err != nil { logger.Error(err.Error()) } else { manners.Close() dispChan <- dispatcher } } }() logger.Info("waiting to die") <-done }