2017-04-17 23:47:53 +03:00
package server
2016-01-14 00:45:49 +03:00
import (
2016-08-16 18:26:10 +03:00
"context"
2016-02-26 17:29:53 +03:00
"os"
"os/signal"
"time"
2016-02-20 01:55:23 +03:00
2019-08-03 04:58:23 +03:00
"github.com/containous/traefik/v2/pkg/log"
"github.com/containous/traefik/v2/pkg/metrics"
"github.com/containous/traefik/v2/pkg/middlewares/accesslog"
"github.com/containous/traefik/v2/pkg/safe"
2019-11-14 18:40:05 +03:00
"github.com/containous/traefik/v2/pkg/server/middleware"
2016-01-14 00:45:49 +03:00
)
// Server is the reverse-proxy/load-balancer engine
type Server struct {
2019-11-14 18:40:05 +03:00
watcher * ConfigurationWatcher
tcpEntryPoints TCPEntryPoints
chainBuilder * middleware . ChainBuilder
2018-04-23 16:30:03 +03:00
2019-11-14 18:40:05 +03:00
accessLoggerMiddleware * accesslog . Handler
2019-06-28 01:16:04 +03:00
2019-11-14 18:40:05 +03:00
signals chan os . Signal
stopChan chan bool
2019-06-28 01:16:04 +03:00
2019-11-14 18:40:05 +03:00
routinesPool * safe . Pool
2018-11-14 12:18:03 +03:00
}
2016-01-14 00:45:49 +03:00
// NewServer returns an initialized Server.
2019-11-14 18:40:05 +03:00
func NewServer ( routinesPool * safe . Pool , entryPoints TCPEntryPoints , watcher * ConfigurationWatcher ,
chainBuilder * middleware . ChainBuilder , accessLoggerMiddleware * accesslog . Handler ) * Server {
srv := & Server {
watcher : watcher ,
tcpEntryPoints : entryPoints ,
chainBuilder : chainBuilder ,
accessLoggerMiddleware : accessLoggerMiddleware ,
signals : make ( chan os . Signal , 1 ) ,
stopChan : make ( chan bool , 1 ) ,
routinesPool : routinesPool ,
2019-09-06 16:08:04 +03:00
}
2019-11-14 18:40:05 +03:00
srv . configureSignals ( )
2018-11-14 12:18:03 +03:00
2019-11-14 18:40:05 +03:00
return srv
2016-01-14 00:45:49 +03:00
}
2018-11-27 19:42:04 +03:00
// Start starts the server and Stop/Close it when context is Done
func ( s * Server ) Start ( ctx context . Context ) {
go func ( ) {
<- ctx . Done ( )
logger := log . FromContext ( ctx )
logger . Info ( "I have to go..." )
logger . Info ( "Stopping server gracefully" )
s . Stop ( )
} ( )
2019-11-14 18:40:05 +03:00
s . tcpEntryPoints . Start ( )
s . watcher . Start ( )
2019-12-09 17:14:06 +03:00
s . routinesPool . Go ( s . listenSignals )
2016-10-25 18:59:39 +03:00
}
2019-11-14 18:40:05 +03:00
// Wait blocks until the server shutdown.
2017-11-24 21:18:03 +03:00
func ( s * Server ) Wait ( ) {
<- s . stopChan
2016-01-14 00:45:49 +03:00
}
// Stop stops the server
2017-11-24 21:18:03 +03:00
func ( s * Server ) Stop ( ) {
2018-11-14 12:18:03 +03:00
defer log . WithoutContext ( ) . Info ( "Server stopped" )
2019-11-14 18:40:05 +03:00
s . tcpEntryPoints . Stop ( )
2018-11-14 12:18:03 +03:00
2017-11-24 21:18:03 +03:00
s . stopChan <- true
2016-01-14 00:45:49 +03:00
}
// Close destroys the server
2017-11-24 21:18:03 +03:00
func ( s * Server ) Close ( ) {
2018-03-14 15:14:03 +03:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , 10 * time . Second )
2019-11-14 18:40:05 +03:00
2016-07-13 18:50:57 +03:00
go func ( ctx context . Context ) {
<- ctx . Done ( )
if ctx . Err ( ) == context . Canceled {
return
} else if ctx . Err ( ) == context . DeadlineExceeded {
2018-03-14 15:14:03 +03:00
panic ( "Timeout while stopping traefik, killing instance ✝" )
2016-07-13 18:50:57 +03:00
}
} ( ctx )
2018-11-14 12:18:03 +03:00
2017-08-23 21:46:03 +03:00
stopMetricsClients ( )
2019-11-14 18:40:05 +03:00
2017-11-24 21:18:03 +03:00
s . routinesPool . Cleanup ( )
2019-11-14 18:40:05 +03:00
2017-11-24 21:18:03 +03:00
signal . Stop ( s . signals )
close ( s . signals )
2018-11-14 12:18:03 +03:00
2019-11-14 18:40:05 +03:00
close ( s . stopChan )
2018-11-14 12:18:03 +03:00
2019-11-14 18:40:05 +03:00
s . chainBuilder . Close ( )
2018-11-14 12:18:03 +03:00
2016-07-13 18:50:57 +03:00
cancel ( )
2016-01-14 00:45:49 +03:00
}
2017-08-23 21:46:03 +03:00
func stopMetricsClients ( ) {
metrics . StopDatadog ( )
metrics . StopStatsd ( )
2017-11-08 17:14:03 +03:00
metrics . StopInfluxDB ( )
2017-07-21 01:26:43 +03:00
}