From 8401cccff25b05f73b33c99a3abfa2ab88b1a383 Mon Sep 17 00:00:00 2001 From: Emile Vauge Date: Thu, 9 Mar 2017 23:27:09 +0100 Subject: [PATCH] Replace mailgun/manners with go 1.8 graceful shutdown Signed-off-by: Emile Vauge --- README.md | 1 - glide.lock | 136 ++--------------------------------------------------- glide.yaml | 1 - server.go | 62 +++++++++++------------- 4 files changed, 31 insertions(+), 169 deletions(-) diff --git a/README.md b/README.md index 7164eaeb3..fbe3d3b5e 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,6 @@ You can access to a simple HTML frontend of Træfik. - [Oxy](https://github.com/vulcand/oxy): an awesome proxy library made by Mailgun guys - [Gorilla mux](https://github.com/gorilla/mux): famous request router - [Negroni](https://github.com/codegangsta/negroni): web middlewares made simple -- [Manners](https://github.com/mailgun/manners): graceful shutdown of http.Handler servers - [Lego](https://github.com/xenolf/lego): the best [Let's Encrypt](https://letsencrypt.org) library in go ## Test it diff --git a/glide.lock b/glide.lock index d5e54a57b..118013102 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: 9d7c36c335fe9106ec79cb86a3b3824c23b63d3fb3a3fb4c75bd6915f3afcdd4 -updated: 2017-03-08T18:53:12.139107148-07:00 +hash: 56175c5c588abf1169ba2425ac6dd7e3e5a8cf8ab6ad3f75cad51e45f5e94e3a +updated: 2017-03-23T22:43:06.217624505+01:00 imports: - name: bitbucket.org/ww/goautoneg version: 75cd24fc2f2c2a2088577d12123ddee5f54e0675 @@ -132,78 +132,12 @@ imports: - name: github.com/docker/distribution version: 325b0804fef3a66309d962357aac3c2ce3f4d329 subpackages: - - context - digest - reference - - registry/api/errcode - - registry/api/v2 - - registry/client - - registry/client/auth - - registry/client/auth/challenge - - registry/client/transport - - registry/storage/cache - - registry/storage/cache/memory - - uuid - name: github.com/docker/docker version: 49bf474f9ed7ce7143a59d1964ff7b7fd9b52178 subpackages: - - api/types - - api/types/backend - - api/types/blkiodev - - api/types/container - - api/types/filters - - api/types/mount - - api/types/network - - api/types/registry - - api/types/strslice - - api/types/swarm - - api/types/versions - - builder - - builder/dockerignore - - cliconfig - - cliconfig/configfile - - daemon/graphdriver - - image - - image/v1 - - layer - namesgenerator - - oci - - opts - - pkg/archive - - pkg/chrootarchive - - pkg/fileutils - - pkg/gitutils - - pkg/homedir - - pkg/httputils - - pkg/idtools - - pkg/ioutils - - pkg/jsonlog - - pkg/jsonmessage - - pkg/longpath - - pkg/mount - - pkg/namesgenerator - - pkg/plugingetter - - pkg/plugins - - pkg/plugins/transport - - pkg/pools - - pkg/progress - - pkg/promise - - pkg/random - - pkg/reexec - - pkg/signal - - pkg/stdcopy - - pkg/streamformatter - - pkg/stringid - - pkg/symlink - - pkg/system - - pkg/tarsum - - pkg/term - - pkg/term/windows - - pkg/urlutil - - plugin/v2 - - reference - - registry - - runconfig/opts - name: github.com/docker/engine-api version: 3d1601b9d2436a70b0dfc045a23f6503d19195df subpackages: @@ -329,8 +263,6 @@ imports: version: 72f9bd7c4e0c2a40055ab3d0f09654f730cce982 - name: github.com/juju/ratelimit version: 77ed1c8a01217656d2080ad51981f6e99adaa177 -- name: github.com/mailgun/manners - version: a585afd9d65c0e05f6c003f921e71ebc05074f4f - name: github.com/mailgun/timetools version: fd192d755b00c968d312d23f521eb0cdc6f66bd0 - name: github.com/mailru/easyjson @@ -382,9 +314,6 @@ imports: - name: github.com/opencontainers/runc version: 1a81e9ab1f138c091fe5c86d0883f87716088527 subpackages: - - libcontainer/configs - - libcontainer/devices - - libcontainer/system - libcontainer/user - name: github.com/ovh/go-ovh version: a8a4c0bc40e56322142649bda7b2b4bb15145b6e @@ -709,63 +638,4 @@ imports: - 1.5/tools/clientcmd/api - 1.5/tools/metrics - 1.5/transport -testImports: -- name: github.com/Azure/go-ansiterm - version: fa152c58bc15761d0200cb75fe958b89a9d4888e - subpackages: - - winterm -- name: github.com/cloudfoundry-incubator/candiedyaml - version: 99c3df83b51532e3615f851d8c2dbb638f5313bf -- name: github.com/docker/libcompose - version: d1876c1d68527a49c0aac22a0b161acc7296b740 - subpackages: - - config - - docker - - docker/builder - - docker/client - - docker/network - - labels - - logger - - lookup - - project - - project/events - - project/options - - utils - - version - - yaml -- name: github.com/flynn/go-shlex - version: 3f9db97f856818214da2e1057f8ad84803971cff -- name: github.com/go-check/check - version: 11d3bc7aa68e238947792f30573146a3231fc0f1 -- name: github.com/gorilla/mux - version: e444e69cbd2e2e3e0749a2f3c717cec491552bbf -- name: github.com/libkermit/compose - version: cadc5a3b83a15790174bd7fbc75ea2529785e772 - subpackages: - - check -- name: github.com/libkermit/docker - version: 55e3595409924fcfbb850811e5a7cdbe8960a0b7 -- name: github.com/libkermit/docker-check - version: cbe0ef03b3d23070eac4d00ba8828f2cc7f7e5a3 -- name: github.com/opencontainers/runtime-spec - version: 06479209bdc0d4135911688c18157bd39bd99c22 - subpackages: - - specs-go -- name: github.com/vbatts/tar-split - version: 6810cedb21b2c3d0b9bb8f9af12ff2dc7a2f14df - subpackages: - - archive/tar - - tar/asm - - tar/storage -- name: github.com/vdemeester/shakers - version: 24d7f1d6a71aa5d9cbe7390e4afb66b7eef9e1b3 -- name: github.com/xeipuuv/gojsonpointer - version: e0fe6f68307607d540ed8eac07a342c33fa1b54a -- name: github.com/xeipuuv/gojsonreference - version: e02fc20de94c78484cd5ffb007f8af96be030a45 -- name: github.com/xeipuuv/gojsonschema - version: 00f9fafb54d2244d291b86ab63d12c38bd5c3886 -- name: golang.org/x/time - version: a4bde12657593d5e90d0533a3e4fd95e635124cb - subpackages: - - rate +testImports: [] diff --git a/glide.yaml b/glide.yaml index abefcda58..80c57a6f4 100644 --- a/glide.yaml +++ b/glide.yaml @@ -47,7 +47,6 @@ import: - package: github.com/hashicorp/consul subpackages: - api -- package: github.com/mailgun/manners - package: github.com/streamrail/concurrent-map - package: github.com/stretchr/testify subpackages: diff --git a/server.go b/server.go index 7e16b2b5e..86adb9c86 100644 --- a/server.go +++ b/server.go @@ -29,13 +29,13 @@ import ( "github.com/containous/traefik/provider" "github.com/containous/traefik/safe" "github.com/containous/traefik/types" - "github.com/mailgun/manners" "github.com/streamrail/concurrent-map" "github.com/vulcand/oxy/cbreaker" "github.com/vulcand/oxy/connlimit" "github.com/vulcand/oxy/forward" "github.com/vulcand/oxy/roundrobin" "github.com/vulcand/oxy/utils" + "sync" ) var oxyLogger = &OxyLogger{} @@ -58,7 +58,7 @@ type Server struct { type serverEntryPoints map[string]*serverEntryPoint type serverEntryPoint struct { - httpServer *manners.GracefulServer + httpServer *http.Server httpRouter *middlewares.HandlerSwitcher } @@ -114,15 +114,23 @@ func (server *Server) Wait() { // Stop stops the server func (server *Server) Stop() { - for serverEntryPointName, serverEntryPoint := range server.serverEntryPoints { - ctx, cancel := context.WithTimeout(context.Background(), time.Duration(server.globalConfiguration.GraceTimeOut)*time.Second) - go func() { - log.Debugf("Waiting %d seconds before killing connections on entrypoint %s...", 30, serverEntryPointName) - serverEntryPoint.httpServer.BlockingClose() + defer log.Info("Server stopped") + var wg sync.WaitGroup + for sepn, sep := range server.serverEntryPoints { + wg.Add(1) + go func(serverEntryPointName string, serverEntryPoint *serverEntryPoint) { + defer wg.Done() + ctx, cancel := context.WithTimeout(context.Background(), time.Duration(server.globalConfiguration.GraceTimeOut)*time.Second) + log.Debugf("Waiting %d seconds before killing connections on entrypoint %s...", server.globalConfiguration.GraceTimeOut, serverEntryPointName) + if err := serverEntryPoint.httpServer.Shutdown(ctx); err != nil { + log.Debugf("Wait is over due to: %s", err) + serverEntryPoint.httpServer.Close() + } cancel() - }() - <-ctx.Done() + log.Debugf("Entrypoint %s closed", serverEntryPointName) + }(sepn, sep) } + wg.Wait() server.stopChan <- true } @@ -191,7 +199,7 @@ func (server *Server) startHTTPServers() { if server.globalConfiguration.EntryPoints[newServerEntryPointName].Compress { serverMiddlewares = append(serverMiddlewares, &middlewares.Compress{}) } - newsrv, err := server.prepareServer(newServerEntryPointName, newServerEntryPoint.httpRouter, server.globalConfiguration.EntryPoints[newServerEntryPointName], nil, serverMiddlewares...) + newsrv, err := server.prepareServer(newServerEntryPointName, newServerEntryPoint.httpRouter, server.globalConfiguration.EntryPoints[newServerEntryPointName], serverMiddlewares...) if err != nil { log.Fatal("Error preparing server: ", err) } @@ -493,21 +501,20 @@ func (server *Server) createTLSConfig(entryPointName string, tlsOption *TLS, rou return config, nil } -func (server *Server) startServer(srv *manners.GracefulServer, globalConfiguration GlobalConfiguration) { +func (server *Server) startServer(srv *http.Server, globalConfiguration GlobalConfiguration) { log.Infof("Starting server on %s", srv.Addr) + var err error if srv.TLSConfig != nil { - if err := srv.ListenAndServeTLSWithConfig(srv.TLSConfig); err != nil { - log.Fatal("Error creating server: ", err) - } + err = srv.ListenAndServeTLS("", "") } else { - if err := srv.ListenAndServe(); err != nil { - log.Fatal("Error creating server: ", err) - } + err = srv.ListenAndServe() + } + if err != nil { + log.Error("Error creating server: ", err) } - log.Info("Server stopped") } -func (server *Server) prepareServer(entryPointName string, router *middlewares.HandlerSwitcher, entryPoint *EntryPoint, oldServer *manners.GracefulServer, middlewares ...negroni.Handler) (*manners.GracefulServer, error) { +func (server *Server) prepareServer(entryPointName string, router *middlewares.HandlerSwitcher, entryPoint *EntryPoint, middlewares ...negroni.Handler) (*http.Server, error) { log.Infof("Preparing server %s %+v", entryPointName, entryPoint) // middlewares var negroni = negroni.New() @@ -521,24 +528,11 @@ func (server *Server) prepareServer(entryPointName string, router *middlewares.H return nil, err } - if oldServer == nil { - return manners.NewWithServer( - &http.Server{ - Addr: entryPoint.Address, - Handler: negroni, - TLSConfig: tlsConfig, - }), nil - } - gracefulServer, err := oldServer.HijackListener(&http.Server{ + return &http.Server{ Addr: entryPoint.Address, Handler: negroni, TLSConfig: tlsConfig, - }, tlsConfig) - if err != nil { - log.Errorf("Error hijacking server: %s", err) - return nil, err - } - return gracefulServer, nil + }, nil } func (server *Server) buildEntryPoints(globalConfiguration GlobalConfiguration) map[string]*serverEntryPoint {