grace.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  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. // Package grace use to hot reload
  15. // Description: http://grisha.org/blog/2014/06/03/graceful-restart-in-golang/
  16. //
  17. // Usage:
  18. //
  19. // import(
  20. // "log"
  21. // "net/http"
  22. // "os"
  23. //
  24. // "github.com/astaxie/beego/grace"
  25. // )
  26. //
  27. // func handler(w http.ResponseWriter, r *http.Request) {
  28. // w.Write([]byte("WORLD!"))
  29. // }
  30. //
  31. // func main() {
  32. // mux := http.NewServeMux()
  33. // mux.HandleFunc("/hello", handler)
  34. //
  35. // err := grace.ListenAndServe("localhost:8080", mux)
  36. // if err != nil {
  37. // log.Println(err)
  38. // }
  39. // log.Println("Server on 8080 stopped")
  40. // os.Exit(0)
  41. // }
  42. package grace
  43. import (
  44. "flag"
  45. "net/http"
  46. "os"
  47. "strings"
  48. "sync"
  49. "syscall"
  50. "time"
  51. )
  52. const (
  53. // PreSignal is the position to add filter before signal
  54. PreSignal = iota
  55. // PostSignal is the position to add filter after signal
  56. PostSignal
  57. // StateInit represent the application inited
  58. StateInit
  59. // StateRunning represent the application is running
  60. StateRunning
  61. // StateShuttingDown represent the application is shutting down
  62. StateShuttingDown
  63. // StateTerminate represent the application is killed
  64. StateTerminate
  65. )
  66. var (
  67. regLock *sync.Mutex
  68. runningServers map[string]*Server
  69. runningServersOrder []string
  70. socketPtrOffsetMap map[string]uint
  71. runningServersForked bool
  72. // DefaultReadTimeOut is the HTTP read timeout
  73. DefaultReadTimeOut time.Duration
  74. // DefaultWriteTimeOut is the HTTP Write timeout
  75. DefaultWriteTimeOut time.Duration
  76. // DefaultMaxHeaderBytes is the Max HTTP Herder size, default is 0, no limit
  77. DefaultMaxHeaderBytes int
  78. // DefaultTimeout is the shutdown server's timeout. default is 60s
  79. DefaultTimeout = 60 * time.Second
  80. isChild bool
  81. socketOrder string
  82. hookableSignals []os.Signal
  83. )
  84. func init() {
  85. flag.BoolVar(&isChild, "graceful", false, "listen on open fd (after forking)")
  86. flag.StringVar(&socketOrder, "socketorder", "", "previous initialization order - used when more than one listener was started")
  87. regLock = &sync.Mutex{}
  88. runningServers = make(map[string]*Server)
  89. runningServersOrder = []string{}
  90. socketPtrOffsetMap = make(map[string]uint)
  91. hookableSignals = []os.Signal{
  92. syscall.SIGHUP,
  93. syscall.SIGINT,
  94. syscall.SIGTERM,
  95. }
  96. }
  97. // NewServer returns a new graceServer.
  98. func NewServer(addr string, handler http.Handler) (srv *Server) {
  99. regLock.Lock()
  100. defer regLock.Unlock()
  101. if !flag.Parsed() {
  102. flag.Parse()
  103. }
  104. if len(socketOrder) > 0 {
  105. for i, addr := range strings.Split(socketOrder, ",") {
  106. socketPtrOffsetMap[addr] = uint(i)
  107. }
  108. } else {
  109. socketPtrOffsetMap[addr] = uint(len(runningServersOrder))
  110. }
  111. srv = &Server{
  112. wg: sync.WaitGroup{},
  113. sigChan: make(chan os.Signal),
  114. isChild: isChild,
  115. SignalHooks: map[int]map[os.Signal][]func(){
  116. PreSignal: {
  117. syscall.SIGHUP: {},
  118. syscall.SIGINT: {},
  119. syscall.SIGTERM: {},
  120. },
  121. PostSignal: {
  122. syscall.SIGHUP: {},
  123. syscall.SIGINT: {},
  124. syscall.SIGTERM: {},
  125. },
  126. },
  127. state: StateInit,
  128. Network: "tcp",
  129. }
  130. srv.Server = &http.Server{}
  131. srv.Server.Addr = addr
  132. srv.Server.ReadTimeout = DefaultReadTimeOut
  133. srv.Server.WriteTimeout = DefaultWriteTimeOut
  134. srv.Server.MaxHeaderBytes = DefaultMaxHeaderBytes
  135. srv.Server.Handler = handler
  136. runningServersOrder = append(runningServersOrder, addr)
  137. runningServers[addr] = srv
  138. return
  139. }
  140. // ListenAndServe refer http.ListenAndServe
  141. func ListenAndServe(addr string, handler http.Handler) error {
  142. server := NewServer(addr, handler)
  143. return server.ListenAndServe()
  144. }
  145. // ListenAndServeTLS refer http.ListenAndServeTLS
  146. func ListenAndServeTLS(addr string, certFile string, keyFile string, handler http.Handler) error {
  147. server := NewServer(addr, handler)
  148. return server.ListenAndServeTLS(certFile, keyFile)
  149. }