mirror of
https://github.com/nais/wonderwall.git
synced 2026-05-06 00:17:27 +00:00
feat(server): support wait before triggering graceful shutdown
This commit is contained in:
@@ -14,10 +14,12 @@ import (
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
BindAddress string `json:"bind-address"`
|
||||
LogFormat string `json:"log-format"`
|
||||
LogLevel string `json:"log-level"`
|
||||
MetricsBindAddress string `json:"metrics-bind-address"`
|
||||
BindAddress string `json:"bind-address"`
|
||||
LogFormat string `json:"log-format"`
|
||||
LogLevel string `json:"log-level"`
|
||||
MetricsBindAddress string `json:"metrics-bind-address"`
|
||||
ShutdownGracefulPeriod time.Duration `json:"shutdown-graceful-period"`
|
||||
ShutdownWaitBeforePeriod time.Duration `json:"shutdown-wait-before-period"`
|
||||
|
||||
AutoLogin bool `json:"auto-login"`
|
||||
AutoLoginIgnorePaths []string `json:"auto-login-ignore-paths"`
|
||||
@@ -63,10 +65,12 @@ const (
|
||||
)
|
||||
|
||||
const (
|
||||
BindAddress = "bind-address"
|
||||
LogFormat = "log-format"
|
||||
LogLevel = "log-level"
|
||||
MetricsBindAddress = "metrics-bind-address"
|
||||
BindAddress = "bind-address"
|
||||
LogFormat = "log-format"
|
||||
LogLevel = "log-level"
|
||||
MetricsBindAddress = "metrics-bind-address"
|
||||
ShutdownGracefulPeriod = "shutdown-graceful-period"
|
||||
ShutdownWaitBeforePeriod = "shutdown-wait-before-period"
|
||||
|
||||
AutoLogin = "auto-login"
|
||||
AutoLoginIgnorePaths = "auto-login-ignore-paths"
|
||||
@@ -97,6 +101,8 @@ func Initialize() (*Config, error) {
|
||||
flag.String(LogFormat, "json", "Log format, either 'json' or 'text'.")
|
||||
flag.String(LogLevel, "info", "Logging verbosity level.")
|
||||
flag.String(MetricsBindAddress, "127.0.0.1:3001", "Listen address for metrics only.")
|
||||
flag.Duration(ShutdownGracefulPeriod, 30*time.Second, "Graceful shutdown period when receiving a shutdown signal after which the server is forcibly exited.")
|
||||
flag.Duration(ShutdownWaitBeforePeriod, 0*time.Second, "Wait period when receiving a shutdown signal before actually starting a graceful shutdown. Useful for allowing propagation of Endpoint updates in Kubernetes.")
|
||||
|
||||
flag.Bool(AutoLogin, false, "Automatically redirect all HTTP GET requests to login if the user does not have a valid session for all matching upstream paths.")
|
||||
flag.StringSlice(AutoLoginIgnorePaths, []string{}, "Comma separated list of absolute paths to ignore when 'auto-login' is enabled. Supports basic wildcard matching with glob-style asterisks. Invalid patterns are ignored.")
|
||||
@@ -222,6 +228,10 @@ func (c *Config) Validate() error {
|
||||
return fmt.Errorf("%q must be set when %q is set (was %q)", UpstreamPort, UpstreamIP, c.UpstreamIP)
|
||||
}
|
||||
|
||||
if c.ShutdownGracefulPeriod <= c.ShutdownWaitBeforePeriod {
|
||||
return fmt.Errorf("%q must be greater than %q", ShutdownGracefulPeriod, ShutdownWaitBeforePeriod)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -44,17 +44,22 @@ func Start(cfg *config.Config, r chi.Router) error {
|
||||
sig := make(chan os.Signal, 1)
|
||||
signal.Notify(sig, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
|
||||
go func() {
|
||||
<-sig
|
||||
s := <-sig
|
||||
log.Infof("server: received %q; waiting for %s before starting graceful shutdown...", s, cfg.ShutdownWaitBeforePeriod)
|
||||
time.Sleep(cfg.ShutdownWaitBeforePeriod)
|
||||
|
||||
shutdownCtx, shutdownStopCtx := context.WithTimeout(serverCtx, 20*time.Second)
|
||||
// the total terminationGracePeriodSeconds in Kubernetes starts immediately when SIGTERM is sent, so we need to subtract the wait-before period to exit before SIGKILL
|
||||
shutdownTimeout := cfg.ShutdownGracefulPeriod - cfg.ShutdownWaitBeforePeriod
|
||||
shutdownCtx, shutdownStopCtx := context.WithTimeout(serverCtx, shutdownTimeout)
|
||||
|
||||
go func() {
|
||||
<-shutdownCtx.Done()
|
||||
if shutdownCtx.Err() == context.DeadlineExceeded {
|
||||
log.Fatal("graceful shutdown timed out.. forcing exit.")
|
||||
log.Fatalf("server: graceful shutdown timed out after %s; forcing exit.", shutdownTimeout)
|
||||
}
|
||||
}()
|
||||
|
||||
log.Infof("server: starting graceful shutdown (will timeout after %s)...", shutdownTimeout)
|
||||
err := server.Shutdown(shutdownCtx)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
@@ -69,5 +74,6 @@ func Start(cfg *config.Config, r chi.Router) error {
|
||||
}
|
||||
|
||||
<-serverCtx.Done()
|
||||
log.Infof("server: shutdown completed")
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user