Ejemplo n.º 1
0
Archivo: app.go Proyecto: fkasper/core
// 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)
}
Ejemplo n.º 2
0
Archivo: etcd.go Proyecto: fkasper/core
// Subscribe watches etcd changes and generates structured events telling vulcand to add or delete frontends, hosts etc.
// It is a blocking function.
func (n *ng) Subscribe(changes chan interface{}, cancelC chan bool) error {
	// This index helps us to get changes in sequence, as they were performed by clients.
	waitIndex := uint64(0)
	for {
		response, err := n.client.Watch(n.etcdKey, waitIndex, true, nil, cancelC)
		if err != nil {
			switch err {
			case etcd.ErrWatchStoppedByUser:
				log.Infof("Stop watching: graceful shutdown")
				return nil
			default:
				log.Errorf("unexpected error: %s, stop watching", err)
				return err
			}
		}
		waitIndex = response.Node.ModifiedIndex + 1
		log.Infof("%s", responseToString(response))
		change, err := n.parseChange(response)
		if err != nil {
			log.Warningf("Ignore '%s', error: %s", responseToString(response), err)
			continue
		}
		if change != nil {
			log.Infof("%v", change)
			select {
			case changes <- change:
			case <-cancelC:
				return nil
			}
		}
	}
}
Ejemplo n.º 3
0
Archivo: etcd.go Proyecto: fkasper/core
func (n *ng) buildDbCluster() error {
	dbEndpoints := n.path("cassandra", "hosts")

	var cassandraPool *cassandraPool
	err := n.getJSONVal(dbEndpoints, &cassandraPool)
	if err != nil {
		return err
	}

	log.Infof("===> Syncing up Migrations with the cluster")
	allErr, ok := migrate.UpSync("cassandra://"+cassandraPool.Nodes[0]+"/"+cassandraPool.Keyspace, "./migrations")
	if !ok {
		return allErr[0]
	}
	log.Infof("===> Migrations are in sync")
	log.Infof("===> Connecting to the database cluster")

	db := gocql.NewCluster(cassandraPool.Nodes...)
	db.Keyspace = cassandraPool.Keyspace
	db.NumConns = cassandraPool.NumConns
	db.DiscoverHosts = true
	db.Discovery = gocql.DiscoveryConfig{
		DcFilter:   "",
		RackFilter: "",
		Sleep:      30 * time.Second,
	}
	n.Database = db
	log.Infof("===> Connected to the database cluster")

	return nil
}
Ejemplo n.º 4
0
// Stop halts sending heartbeats.
func (h *Heartbeater) Stop() {
	log.Infof("Stopping heartbeat for app: %v", h.registration)

	close(h.quit)
	h.ticker.Stop()
	h.Running = false
}
Ejemplo n.º 5
0
// Make a handler out of HandlerWithBodyFunc, just like regular MakeHandler function.
func MakeHandlerWithBody(app *App, fn HandlerWithBodyFunc, spec Spec) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		if err := parseForm(r); err != nil {
			ReplyInternalError(w, fmt.Sprintf("Failed to parse request form: %v", err))
			return
		}

		body, err := ioutil.ReadAll(r.Body)
		if err != nil {
			ReplyInternalError(w, fmt.Sprintf("Failed to read request body: %v", err))
			return
		}

		start := time.Now()
		response, err := fn(w, r, mux.Vars(r), body)
		elapsedTime := time.Since(start)

		var status int
		if err != nil {
			response, status = responseAndStatusFor(err)
		} else {
			status = http.StatusOK
		}

		log.Infof("Request(Status=%v, Method=%v, Path=%v, Form=%v, Time=%v, Error=%v)",
			status, r.Method, r.URL, r.Form, elapsedTime, err)

		app.stats.TrackRequest(spec.MetricName, status, elapsedTime)

		Reply(w, response, status)
	}
}
Ejemplo n.º 6
0
// RegisterApp adds a new backend and a single server with Vulcand.
func (s *LeaderRegistry) RegisterApp(registration *AppRegistration) error {
	log.Infof("Registering app: %v", registration)

	endpoint, err := vulcan.NewEndpointWithID(s.Group, registration.Name, registration.Host, registration.Port)
	if err != nil {
		return err
	}

	err = s.client.RegisterBackend(endpoint)
	if err != nil {
		log.Errorf("Failed to register backend for endpoint: %v, %s", endpoint, err)
		return err
	}

	if s.IsMaster {
		err = s.maintainLeader(endpoint)
	} else {
		err = s.initLeader(endpoint)
	}

	if err != nil {
		log.Errorf("Failed to register server for endpoint: %v, %s", endpoint, err)
		return err
	}

	return nil
}
Ejemplo n.º 7
0
// Start begins sending heartbeats.
func (h *Heartbeater) Start() {
	log.Infof("Starting heartbeat for app: %v", h.registration)

	h.Running = true
	h.ticker = time.NewTicker(h.interval)
	h.quit = make(chan int)

	go h.heartbeat()
}
Ejemplo n.º 8
0
func (s *LeaderRegistry) maintainLeader(endpoint *vulcan.Endpoint) error {
	err := s.client.UpdateServer(endpoint, s.TTL)
	if err != nil {
		log.Infof("Falling back to follow role for endpoint: %v", endpoint)
		s.IsMaster = false
		return err
	}

	return nil
}
Ejemplo n.º 9
0
func (s *LeaderRegistry) initLeader(endpoint *vulcan.Endpoint) error {
	err := s.client.CreateServer(endpoint, s.TTL)
	if err != nil {
		return err
	}

	log.Infof("Assumed master role for endpoint: %v", endpoint)
	s.IsMaster = true

	return nil
}
Ejemplo n.º 10
0
// Helper method to retrieve an optional timestamp from POST request field.
// If no timestamp provided, returns current time.
// Returns `InvalidFormatError` if provided timestamp can't be parsed.
func GetTimestampField(r *http.Request, fieldName string) (time.Time, error) {
	if _, ok := r.Form[fieldName]; !ok {
		return time.Now(), MissingFieldError{fieldName}
	}
	parsedTime, err := time.Parse(time.RFC1123, r.FormValue(fieldName))
	if err != nil {
		log.Infof("Failed to convert timestamp %v: %v", r.FormValue(fieldName), err)
		return time.Now(), InvalidFormatError{fieldName, r.FormValue(fieldName)}
	}
	return parsedTime, nil
}
Ejemplo n.º 11
0
Archivo: app.go Proyecto: fkasper/core
// registerLocationForHost registers a location for a specified hostname.
func (app *App) registerLocationForHost(methods []string, path, host string, middlewares []middleware.Middleware) {
	r := &registry.HandlerRegistration{
		Name:        app.Config.Name,
		Host:        host,
		Path:        path,
		Methods:     methods,
		Middlewares: middlewares,
	}
	app.Config.Registry.RegisterHandler(r)

	log.Infof("Registered: %v", r)
}
Ejemplo n.º 12
0
func (s *Service) reportSystemMetrics() {
	defer func() {
		if r := recover(); r != nil {
			log.Infof("Recovered in reportSystemMetrics", r)
		}
	}()
	for {
		s.metricsClient.ReportRuntimeMetrics("sys", 1.0)
		// we have 256 time buckets for gc stats, GC is being executed every 4ms on average
		// so we have 256 * 4 = 1024 around one second to report it. To play safe, let's report every 300ms
		time.Sleep(300 * time.Millisecond)
	}
}
Ejemplo n.º 13
0
func Run() error {
	options, err := ParseCommandLine()
	if err != nil {
		return fmt.Errorf("failed to parse command line: %s", err)
	}
	service := NewService(options)
	if err := service.Start(); err != nil {
		log.Errorf("Failed to start service: %v", err)
		return fmt.Errorf("service start failure: %s", err)
	} else {
		log.Infof("Service exited gracefully")
	}
	return nil
}
Ejemplo n.º 14
0
// RegisterHandler registers the frontends and middlewares with Vulcand.
func (s *LeaderRegistry) RegisterHandler(registration *HandlerRegistration) error {
	log.Infof("Registering handler: %v", registration)

	location := vulcan.NewLocation(registration.Host, registration.Methods, registration.Path, registration.Name, registration.Middlewares)
	err := s.client.RegisterFrontend(location)
	if err != nil {
		log.Errorf("Failed to register frontend for location: %v, %s", location, err)
		return err
	}

	err = s.client.RegisterMiddleware(location)
	if err != nil {
		log.Errorf("Failed to register middleware for location: %v, %s", location, err)
		return err
	}

	return nil
}
Ejemplo n.º 15
0
Archivo: lb.go Proyecto: fkasper/core
// RegisterApp adds a new backend and a single server with Vulcand.
func (s *LBRegistry) RegisterApp(registration *AppRegistration) error {
	log.Infof("Registering app: %v", registration)

	endpoint, err := vulcan.NewEndpoint(registration.Name, registration.Host, registration.Port)
	if err != nil {
		return err
	}

	err = s.client.RegisterBackend(endpoint)
	if err != nil {
		log.Errorf("Failed to register backend for endpoint: %v, %s", endpoint, err)
		return err
	}

	err = s.client.UpsertServer(endpoint, s.TTL)
	if err != nil {
		log.Errorf("Failed to register server for endpoint: %v, %s", endpoint, err)
		return err
	}

	return nil
}
Ejemplo n.º 16
0
Archivo: api.go Proyecto: fkasper/core
func (c *ProxyController) handleError(w http.ResponseWriter, r *http.Request) {
	log.Infof("not found")
	scroll.ReplyError(w, scroll.NotFoundError{Description: "Object not found"})
}
Ejemplo n.º 17
0
Archivo: nop.go Proyecto: fkasper/core
// RegisterApp is a no-op.
func (s *NopRegistry) RegisterApp(*AppRegistration) error {
	log.Infof("Skipping application registration for NopRegistry")
	return nil
}
Ejemplo n.º 18
0
Archivo: nop.go Proyecto: fkasper/core
// RegisterHandler is a no-op.
func (s *NopRegistry) RegisterHandler(*HandlerRegistration) error {
	log.Infof("Skipping handler registration for NopRegistry")
	return nil
}
Ejemplo n.º 19
0
func (s *Service) Start() error {
	log.InitWithConfig(log.Config{
		Name:     s.options.Log,
		Severity: s.options.LogSeverity.S.String(),
	})

	log.Infof("Service starts with options: %#v", s.options)

	if s.options.PidPath != "" {
		ioutil.WriteFile(s.options.PidPath, []byte(fmt.Sprint(os.Getpid())), 0644)
	}

	if s.options.StatsdAddr != "" {
		var err error
		s.metricsClient, err = metrics.NewWithOptions(s.options.StatsdAddr, s.options.StatsdPrefix, metrics.Options{UseBuffering: true})
		if err != nil {
			return err
		}
	}

	// apiFile, muxFiles, err := s.getFiles()
	// if err != nil {
	// 	return err
	// }

	// if err := s.newEngine(); err != nil {
	// 	return err
	// }

	// s.stapler = stapler.New()
	// s.supervisor = supervisor.New(
	// 	s.newProxy, s.ng, s.errorC, supervisor.Options{Files: muxFiles})

	// Tells configurator to perform initial proxy configuration and start watching changes
	// if err := s.supervisor.Start(); err != nil {
	// 	return err
	// }
	if err := s.newEngine(); err != nil {
		return err
	}

	if err := s.initApi(); err != nil {
		return err
	}

	go func() {
		s.errorC <- s.startApi()
	}()

	if s.metricsClient != nil {
		go s.reportSystemMetrics()
	}
	signal.Notify(s.sigC, os.Interrupt, os.Kill, syscall.SIGTERM, syscall.SIGUSR2, syscall.SIGCHLD)

	// Block until a signal is received or we got an error
	for {
		select {
		case signal := <-s.sigC:
			switch signal {
			case syscall.SIGTERM, syscall.SIGINT:
				log.Infof("Got signal '%s', shutting down gracefully", signal)
				//s.supervisor.Stop(true)
				log.Infof("All servers stopped")
				return nil
			case syscall.SIGKILL:
				log.Infof("Got signal '%s', exiting now without waiting", signal)
				//s.supervisor.Stop(false)
				return nil
			default:
				log.Infof("Ignoring '%s'", signal)
			}
		case err := <-s.errorC:
			log.Infof("Got request to shutdown with error: %s", err)
			return err
		}
	}
}