github.com/astaxie/beego@v1.12.3/grace/grace.go (about)

     1  // Copyright 2014 beego Author. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Package grace use to hot reload
    16  // Description: http://grisha.org/blog/2014/06/03/graceful-restart-in-golang/
    17  //
    18  // Usage:
    19  //
    20  // import(
    21  //   "log"
    22  //	 "net/http"
    23  //	 "os"
    24  //
    25  //   "github.com/astaxie/beego/grace"
    26  // )
    27  //
    28  //  func handler(w http.ResponseWriter, r *http.Request) {
    29  //	  w.Write([]byte("WORLD!"))
    30  //  }
    31  //
    32  //  func main() {
    33  //      mux := http.NewServeMux()
    34  //      mux.HandleFunc("/hello", handler)
    35  //
    36  //	    err := grace.ListenAndServe("localhost:8080", mux)
    37  //      if err != nil {
    38  //		   log.Println(err)
    39  //	    }
    40  //      log.Println("Server on 8080 stopped")
    41  //	     os.Exit(0)
    42  //    }
    43  package grace
    44  
    45  import (
    46  	"flag"
    47  	"net/http"
    48  	"os"
    49  	"strings"
    50  	"sync"
    51  	"syscall"
    52  	"time"
    53  )
    54  
    55  const (
    56  	// PreSignal is the position to add filter before signal
    57  	PreSignal = iota
    58  	// PostSignal is the position to add filter after signal
    59  	PostSignal
    60  	// StateInit represent the application inited
    61  	StateInit
    62  	// StateRunning represent the application is running
    63  	StateRunning
    64  	// StateShuttingDown represent the application is shutting down
    65  	StateShuttingDown
    66  	// StateTerminate represent the application is killed
    67  	StateTerminate
    68  )
    69  
    70  var (
    71  	regLock              *sync.Mutex
    72  	runningServers       map[string]*Server
    73  	runningServersOrder  []string
    74  	socketPtrOffsetMap   map[string]uint
    75  	runningServersForked bool
    76  
    77  	// DefaultReadTimeOut is the HTTP read timeout
    78  	DefaultReadTimeOut time.Duration
    79  	// DefaultWriteTimeOut is the HTTP Write timeout
    80  	DefaultWriteTimeOut time.Duration
    81  	// DefaultMaxHeaderBytes is the Max HTTP Header size, default is 0, no limit
    82  	DefaultMaxHeaderBytes int
    83  	// DefaultTimeout is the shutdown server's timeout. default is 60s
    84  	DefaultTimeout = 60 * time.Second
    85  
    86  	isChild     bool
    87  	socketOrder string
    88  
    89  	hookableSignals []os.Signal
    90  )
    91  
    92  func init() {
    93  	flag.BoolVar(&isChild, "graceful", false, "listen on open fd (after forking)")
    94  	flag.StringVar(&socketOrder, "socketorder", "", "previous initialization order - used when more than one listener was started")
    95  
    96  	regLock = &sync.Mutex{}
    97  	runningServers = make(map[string]*Server)
    98  	runningServersOrder = []string{}
    99  	socketPtrOffsetMap = make(map[string]uint)
   100  
   101  	hookableSignals = []os.Signal{
   102  		syscall.SIGHUP,
   103  		syscall.SIGINT,
   104  		syscall.SIGTERM,
   105  	}
   106  }
   107  
   108  // NewServer returns a new graceServer.
   109  func NewServer(addr string, handler http.Handler) (srv *Server) {
   110  	regLock.Lock()
   111  	defer regLock.Unlock()
   112  
   113  	if !flag.Parsed() {
   114  		flag.Parse()
   115  	}
   116  	if len(socketOrder) > 0 {
   117  		for i, addr := range strings.Split(socketOrder, ",") {
   118  			socketPtrOffsetMap[addr] = uint(i)
   119  		}
   120  	} else {
   121  		socketPtrOffsetMap[addr] = uint(len(runningServersOrder))
   122  	}
   123  
   124  	srv = &Server{
   125  		sigChan: make(chan os.Signal),
   126  		isChild: isChild,
   127  		SignalHooks: map[int]map[os.Signal][]func(){
   128  			PreSignal: {
   129  				syscall.SIGHUP:  {},
   130  				syscall.SIGINT:  {},
   131  				syscall.SIGTERM: {},
   132  			},
   133  			PostSignal: {
   134  				syscall.SIGHUP:  {},
   135  				syscall.SIGINT:  {},
   136  				syscall.SIGTERM: {},
   137  			},
   138  		},
   139  		state:        StateInit,
   140  		Network:      "tcp",
   141  		terminalChan: make(chan error), //no cache channel
   142  	}
   143  	srv.Server = &http.Server{
   144  		Addr:           addr,
   145  		ReadTimeout:    DefaultReadTimeOut,
   146  		WriteTimeout:   DefaultWriteTimeOut,
   147  		MaxHeaderBytes: DefaultMaxHeaderBytes,
   148  		Handler:        handler,
   149  	}
   150  
   151  	runningServersOrder = append(runningServersOrder, addr)
   152  	runningServers[addr] = srv
   153  	return srv
   154  }
   155  
   156  // ListenAndServe refer http.ListenAndServe
   157  func ListenAndServe(addr string, handler http.Handler) error {
   158  	server := NewServer(addr, handler)
   159  	return server.ListenAndServe()
   160  }
   161  
   162  // ListenAndServeTLS refer http.ListenAndServeTLS
   163  func ListenAndServeTLS(addr string, certFile string, keyFile string, handler http.Handler) error {
   164  	server := NewServer(addr, handler)
   165  	return server.ListenAndServeTLS(certFile, keyFile)
   166  }