1
0
mirror of https://github.com/astaxie/beego.git synced 2024-12-22 18:50:50 +00:00

golint grace

This commit is contained in:
astaxie 2015-09-10 16:35:40 +08:00
parent 01a5e54264
commit 65fb7ce391
4 changed files with 58 additions and 46 deletions

View File

@ -4,7 +4,7 @@ import "net"
type graceConn struct {
net.Conn
server *graceServer
server *Server
}
func (c graceConn) Close() error {

View File

@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
// Package grace use to hot reload
// Description: http://grisha.org/blog/2014/06/03/graceful-restart-in-golang/
//
// Usage:
@ -52,26 +53,36 @@ import (
)
const (
PRE_SIGNAL = iota
POST_SIGNAL
// PreSignal is the position to add filter before signal
PreSignal = iota
// PostSignal is the position to add filter after signal
PostSignal
STATE_INIT
STATE_RUNNING
STATE_SHUTTING_DOWN
STATE_TERMINATE
// StateInit represent the application inited
StateInit
// StateRunning represent the application is running
StateRunning
// StateShuttingDown represent the application is shutting down
StateShuttingDown
// StateTerminate represent the application is killed
StateTerminate
)
var (
regLock *sync.Mutex
runningServers map[string]*graceServer
runningServers map[string]*Server
runningServersOrder []string
socketPtrOffsetMap map[string]uint
runningServersForked bool
DefaultReadTimeOut time.Duration
DefaultWriteTimeOut time.Duration
// DefaultReadTimeOut is the HTTP read timeout
DefaultReadTimeOut time.Duration
// DefaultWriteTimeOut is the HTTP Write timeout
DefaultWriteTimeOut time.Duration
// DefaultMaxHeaderBytes is the Max HTTP Herder size, default is 0, no limit
DefaultMaxHeaderBytes int
DefaultTimeout time.Duration
// DefaultTimeout is the shutdown server's timeout. default is 60s
DefaultTimeout time.Duration
isChild bool
socketOrder string
@ -81,7 +92,7 @@ func init() {
regLock = &sync.Mutex{}
flag.BoolVar(&isChild, "graceful", false, "listen on open fd (after forking)")
flag.StringVar(&socketOrder, "socketorder", "", "previous initialization order - used when more than one listener was started")
runningServers = make(map[string]*graceServer)
runningServers = make(map[string]*Server)
runningServersOrder = []string{}
socketPtrOffsetMap = make(map[string]uint)
@ -91,7 +102,7 @@ func init() {
}
// NewServer returns a new graceServer.
func NewServer(addr string, handler http.Handler) (srv *graceServer) {
func NewServer(addr string, handler http.Handler) (srv *Server) {
regLock.Lock()
defer regLock.Unlock()
if !flag.Parsed() {
@ -105,23 +116,23 @@ func NewServer(addr string, handler http.Handler) (srv *graceServer) {
socketPtrOffsetMap[addr] = uint(len(runningServersOrder))
}
srv = &graceServer{
srv = &Server{
wg: sync.WaitGroup{},
sigChan: make(chan os.Signal),
isChild: isChild,
SignalHooks: map[int]map[os.Signal][]func(){
PRE_SIGNAL: map[os.Signal][]func(){
PreSignal: map[os.Signal][]func(){
syscall.SIGHUP: []func(){},
syscall.SIGINT: []func(){},
syscall.SIGTERM: []func(){},
},
POST_SIGNAL: map[os.Signal][]func(){
PostSignal: map[os.Signal][]func(){
syscall.SIGHUP: []func(){},
syscall.SIGINT: []func(){},
syscall.SIGTERM: []func(){},
},
},
state: STATE_INIT,
state: StateInit,
Network: "tcp",
}
srv.Server = &http.Server{}
@ -137,13 +148,13 @@ func NewServer(addr string, handler http.Handler) (srv *graceServer) {
return
}
// refer http.ListenAndServe
// ListenAndServe refer http.ListenAndServe
func ListenAndServe(addr string, handler http.Handler) error {
server := NewServer(addr, handler)
return server.ListenAndServe()
}
// refer http.ListenAndServeTLS
// ListenAndServeTLS refer http.ListenAndServeTLS
func ListenAndServeTLS(addr string, certFile string, keyFile string, handler http.Handler) error {
server := NewServer(addr, handler)
return server.ListenAndServeTLS(certFile, keyFile)

View File

@ -11,10 +11,10 @@ type graceListener struct {
net.Listener
stop chan error
stopped bool
server *graceServer
server *Server
}
func newGraceListener(l net.Listener, srv *graceServer) (el *graceListener) {
func newGraceListener(l net.Listener, srv *Server) (el *graceListener) {
el = &graceListener{
Listener: l,
stop: make(chan error),
@ -46,17 +46,17 @@ func (gl *graceListener) Accept() (c net.Conn, err error) {
return
}
func (el *graceListener) Close() error {
if el.stopped {
func (gl *graceListener) Close() error {
if gl.stopped {
return syscall.EINVAL
}
el.stop <- nil
return <-el.stop
gl.stop <- nil
return <-gl.stop
}
func (el *graceListener) File() *os.File {
func (gl *graceListener) File() *os.File {
// returns a dup(2) - FD_CLOEXEC flag *not* set
tl := el.Listener.(*net.TCPListener)
tl := gl.Listener.(*net.TCPListener)
fl, _ := tl.File()
return fl
}

View File

@ -15,7 +15,8 @@ import (
"time"
)
type graceServer struct {
// Server embedded http.Server
type Server struct {
*http.Server
GraceListener net.Listener
SignalHooks map[int]map[os.Signal][]func()
@ -30,19 +31,19 @@ type graceServer struct {
// Serve accepts incoming connections on the Listener l,
// creating a new service goroutine for each.
// The service goroutines read requests and then call srv.Handler to reply to them.
func (srv *graceServer) Serve() (err error) {
srv.state = STATE_RUNNING
func (srv *Server) Serve() (err error) {
srv.state = StateRunning
err = srv.Server.Serve(srv.GraceListener)
log.Println(syscall.Getpid(), "Waiting for connections to finish...")
srv.wg.Wait()
srv.state = STATE_TERMINATE
srv.state = StateTerminate
return
}
// ListenAndServe listens on the TCP network address srv.Addr and then calls Serve
// to handle requests on incoming connections. If srv.Addr is blank, ":http" is
// used.
func (srv *graceServer) ListenAndServe() (err error) {
func (srv *Server) ListenAndServe() (err error) {
addr := srv.Addr
if addr == "" {
addr = ":http"
@ -83,7 +84,7 @@ func (srv *graceServer) ListenAndServe() (err error) {
// CA's certificate.
//
// If srv.Addr is blank, ":https" is used.
func (srv *graceServer) ListenAndServeTLS(certFile, keyFile string) (err error) {
func (srv *Server) ListenAndServeTLS(certFile, keyFile string) (err error) {
addr := srv.Addr
if addr == "" {
addr = ":https"
@ -131,9 +132,9 @@ func (srv *graceServer) ListenAndServeTLS(certFile, keyFile string) (err error)
// getListener either opens a new socket to listen on, or takes the acceptor socket
// it got passed when restarted.
func (srv *graceServer) getListener(laddr string) (l net.Listener, err error) {
func (srv *Server) getListener(laddr string) (l net.Listener, err error) {
if srv.isChild {
var ptrOffset uint = 0
var ptrOffset uint
if len(socketPtrOffsetMap) > 0 {
ptrOffset = socketPtrOffsetMap[laddr]
log.Println("laddr", laddr, "ptr offset", socketPtrOffsetMap[laddr])
@ -157,7 +158,7 @@ func (srv *graceServer) getListener(laddr string) (l net.Listener, err error) {
// handleSignals listens for os Signals and calls any hooked in function that the
// user had registered with the signal.
func (srv *graceServer) handleSignals() {
func (srv *Server) handleSignals() {
var sig os.Signal
signal.Notify(
@ -170,7 +171,7 @@ func (srv *graceServer) handleSignals() {
pid := syscall.Getpid()
for {
sig = <-srv.sigChan
srv.signalHooks(PRE_SIGNAL, sig)
srv.signalHooks(PreSignal, sig)
switch sig {
case syscall.SIGHUP:
log.Println(pid, "Received SIGHUP. forking.")
@ -187,11 +188,11 @@ func (srv *graceServer) handleSignals() {
default:
log.Printf("Received %v: nothing i care about...\n", sig)
}
srv.signalHooks(POST_SIGNAL, sig)
srv.signalHooks(PostSignal, sig)
}
}
func (srv *graceServer) signalHooks(ppFlag int, sig os.Signal) {
func (srv *Server) signalHooks(ppFlag int, sig os.Signal) {
if _, notSet := srv.SignalHooks[ppFlag][sig]; !notSet {
return
}
@ -204,12 +205,12 @@ func (srv *graceServer) signalHooks(ppFlag int, sig os.Signal) {
// shutdown closes the listener so that no new connections are accepted. it also
// starts a goroutine that will serverTimeout (stop all running requests) the server
// after DefaultTimeout.
func (srv *graceServer) shutdown() {
if srv.state != STATE_RUNNING {
func (srv *Server) shutdown() {
if srv.state != StateRunning {
return
}
srv.state = STATE_SHUTTING_DOWN
srv.state = StateShuttingDown
if DefaultTimeout >= 0 {
go srv.serverTimeout(DefaultTimeout)
}
@ -224,26 +225,26 @@ func (srv *graceServer) shutdown() {
// serverTimeout forces the server to shutdown in a given timeout - whether it
// finished outstanding requests or not. if Read/WriteTimeout are not set or the
// max header size is very big a connection could hang
func (srv *graceServer) serverTimeout(d time.Duration) {
func (srv *Server) serverTimeout(d time.Duration) {
defer func() {
if r := recover(); r != nil {
log.Println("WaitGroup at 0", r)
}
}()
if srv.state != STATE_SHUTTING_DOWN {
if srv.state != StateShuttingDown {
return
}
time.Sleep(d)
log.Println("[STOP - Hammer Time] Forcefully shutting down parent")
for {
if srv.state == STATE_TERMINATE {
if srv.state == StateTerminate {
break
}
srv.wg.Done()
}
}
func (srv *graceServer) fork() (err error) {
func (srv *Server) fork() (err error) {
regLock.Lock()
defer regLock.Unlock()
if runningServersForked {