ghttp_server_graceful.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. // Copyright GoFrame Author(https://github.com/gogf/gf). All Rights Reserved.
  2. //
  3. // This Source Code Form is subject to the terms of the MIT License.
  4. // If a copy of the MIT was not distributed with this file,
  5. // You can obtain one at https://github.com/gogf/gf.
  6. package ghttp
  7. import (
  8. "context"
  9. "crypto/tls"
  10. "errors"
  11. "fmt"
  12. "github.com/gogf/gf/os/gproc"
  13. "github.com/gogf/gf/os/gres"
  14. "github.com/gogf/gf/text/gstr"
  15. "log"
  16. "net"
  17. "net/http"
  18. "os"
  19. )
  20. // gracefulServer wraps the net/http.Server with graceful reload/restart feature.
  21. type gracefulServer struct {
  22. server *Server // Belonged server.
  23. fd uintptr // File descriptor for passing to child process when graceful reload.
  24. address string // Listening address like:":80", ":8080".
  25. httpServer *http.Server // Underlying http.Server.
  26. rawListener net.Listener // Underlying net.Listener.
  27. listener net.Listener // Wrapped net.Listener.
  28. isHttps bool // Is HTTPS.
  29. status int // Status of current server.
  30. }
  31. // newGracefulServer creates and returns a graceful http server with given address.
  32. // The optional parameter <fd> specifies the file descriptor which is passed from parent server.
  33. func (s *Server) newGracefulServer(address string, fd ...int) *gracefulServer {
  34. // Change port to address like: 80 -> :80
  35. if gstr.IsNumeric(address) {
  36. address = ":" + address
  37. }
  38. gs := &gracefulServer{
  39. server: s,
  40. address: address,
  41. httpServer: s.newHttpServer(address),
  42. }
  43. if len(fd) > 0 && fd[0] > 0 {
  44. gs.fd = uintptr(fd[0])
  45. }
  46. return gs
  47. }
  48. // newGracefulServer creates and returns a underlying http.Server with given address.
  49. func (s *Server) newHttpServer(address string) *http.Server {
  50. server := &http.Server{
  51. Addr: address,
  52. Handler: s.config.Handler,
  53. ReadTimeout: s.config.ReadTimeout,
  54. WriteTimeout: s.config.WriteTimeout,
  55. IdleTimeout: s.config.IdleTimeout,
  56. MaxHeaderBytes: s.config.MaxHeaderBytes,
  57. ErrorLog: log.New(&errorLogger{logger: s.config.Logger}, "", 0),
  58. }
  59. server.SetKeepAlivesEnabled(s.config.KeepAlive)
  60. return server
  61. }
  62. // ListenAndServe starts listening on configured address.
  63. func (s *gracefulServer) ListenAndServe() error {
  64. ln, err := s.getNetListener()
  65. if err != nil {
  66. return err
  67. }
  68. s.listener = ln
  69. s.rawListener = ln
  70. return s.doServe()
  71. }
  72. // Fd retrieves and returns the file descriptor of current server.
  73. // It is available ony in *nix like operation systems like: linux, unix, darwin.
  74. func (s *gracefulServer) Fd() uintptr {
  75. if s.rawListener != nil {
  76. file, err := s.rawListener.(*net.TCPListener).File()
  77. if err == nil {
  78. return file.Fd()
  79. }
  80. }
  81. return 0
  82. }
  83. // setFd sets the file descriptor for current server.
  84. func (s *gracefulServer) setFd(fd int) {
  85. s.fd = uintptr(fd)
  86. }
  87. // ListenAndServeTLS starts listening on configured address with HTTPS.
  88. // The parameter <certFile> and <keyFile> specify the necessary certification and key files for HTTPS.
  89. // The optional parameter <tlsConfig> specifies the custom TLS configuration.
  90. func (s *gracefulServer) ListenAndServeTLS(certFile, keyFile string, tlsConfig ...*tls.Config) error {
  91. var config *tls.Config
  92. if len(tlsConfig) > 0 && tlsConfig[0] != nil {
  93. config = tlsConfig[0]
  94. } else if s.httpServer.TLSConfig != nil {
  95. config = s.httpServer.TLSConfig
  96. } else {
  97. config = &tls.Config{}
  98. }
  99. if config.NextProtos == nil {
  100. config.NextProtos = []string{"http/1.1"}
  101. }
  102. err := error(nil)
  103. if len(config.Certificates) == 0 {
  104. config.Certificates = make([]tls.Certificate, 1)
  105. if gres.Contains(certFile) {
  106. config.Certificates[0], err = tls.X509KeyPair(
  107. gres.GetContent(certFile),
  108. gres.GetContent(keyFile),
  109. )
  110. } else {
  111. config.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile)
  112. }
  113. }
  114. if err != nil {
  115. return errors.New(fmt.Sprintf(`open cert file "%s","%s" failed: %s`, certFile, keyFile, err.Error()))
  116. }
  117. ln, err := s.getNetListener()
  118. if err != nil {
  119. return err
  120. }
  121. s.listener = tls.NewListener(ln, config)
  122. s.rawListener = ln
  123. return s.doServe()
  124. }
  125. // getProto retrieves and returns the proto string of current server.
  126. func (s *gracefulServer) getProto() string {
  127. proto := "http"
  128. if s.isHttps {
  129. proto = "https"
  130. }
  131. return proto
  132. }
  133. // doServe does staring the serving.
  134. func (s *gracefulServer) doServe() error {
  135. action := "started"
  136. if s.fd != 0 {
  137. action = "reloaded"
  138. }
  139. s.server.Logger().Printf(
  140. "%d: %s server %s listening on [%s]",
  141. gproc.Pid(), s.getProto(), action, s.address,
  142. )
  143. s.status = ServerStatusRunning
  144. err := s.httpServer.Serve(s.listener)
  145. s.status = ServerStatusStopped
  146. return err
  147. }
  148. // getNetListener retrieves and returns the wrapped net.Listener.
  149. func (s *gracefulServer) getNetListener() (net.Listener, error) {
  150. var ln net.Listener
  151. var err error
  152. if s.fd > 0 {
  153. f := os.NewFile(s.fd, "")
  154. ln, err = net.FileListener(f)
  155. if err != nil {
  156. err = fmt.Errorf("%d: net.FileListener error: %v", gproc.Pid(), err)
  157. return nil, err
  158. }
  159. } else {
  160. ln, err = net.Listen("tcp", s.httpServer.Addr)
  161. if err != nil {
  162. err = fmt.Errorf("%d: net.Listen error: %v", gproc.Pid(), err)
  163. }
  164. }
  165. return ln, err
  166. }
  167. // shutdown shuts down the server gracefully.
  168. func (s *gracefulServer) shutdown() {
  169. if s.status == ServerStatusStopped {
  170. return
  171. }
  172. if err := s.httpServer.Shutdown(context.Background()); err != nil {
  173. s.server.Logger().Errorf(
  174. "%d: %s server [%s] shutdown error: %v",
  175. gproc.Pid(), s.getProto(), s.address, err,
  176. )
  177. }
  178. }
  179. // close shuts down the server forcibly.
  180. func (s *gracefulServer) close() {
  181. if s.status == ServerStatusStopped {
  182. return
  183. }
  184. if err := s.httpServer.Close(); err != nil {
  185. s.server.Logger().Errorf(
  186. "%d: %s server [%s] closed error: %v",
  187. gproc.Pid(), s.getProto(), s.address, err,
  188. )
  189. }
  190. }