Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
B
beego
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
beego
Commits
65fb7ce3
Commit
65fb7ce3
authored
Sep 10, 2015
by
astaxie
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
golint grace
parent
01a5e542
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
59 additions
and
47 deletions
+59
-47
conn.go
grace/conn.go
+1
-1
grace.go
grace/grace.go
+30
-19
listener.go
grace/listener.go
+8
-8
server.go
grace/server.go
+20
-19
No files found.
grace/conn.go
View file @
65fb7ce3
...
...
@@ -4,7 +4,7 @@ import "net"
type
graceConn
struct
{
net
.
Conn
server
*
grace
Server
server
*
Server
}
func
(
c
graceConn
)
Close
()
error
{
...
...
grace/grace.go
View file @
65fb7ce3
...
...
@@ -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
STATE_INIT
STATE_RUNNING
STATE_SHUTTING_DOWN
STATE_TERMINATE
// PreSignal is the position to add filter before signal
PreSignal
=
iota
// PostSignal is the position to add filter after signal
PostSignal
// 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
]
*
grace
Server
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
]
*
grace
Server
)
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
*
grace
Server
)
{
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
=
&
grace
Server
{
srv
=
&
Server
{
wg
:
sync
.
WaitGroup
{},
sigChan
:
make
(
chan
os
.
Signal
),
isChild
:
isChild
,
SignalHooks
:
map
[
int
]
map
[
os
.
Signal
][]
func
(){
P
RE_SIGNAL
:
map
[
os
.
Signal
][]
func
(){
P
reSignal
:
map
[
os
.
Signal
][]
func
(){
syscall
.
SIGHUP
:
[]
func
(){},
syscall
.
SIGINT
:
[]
func
(){},
syscall
.
SIGTERM
:
[]
func
(){},
},
P
OST_SIGNAL
:
map
[
os
.
Signal
][]
func
(){
P
ostSignal
:
map
[
os
.
Signal
][]
func
(){
syscall
.
SIGHUP
:
[]
func
(){},
syscall
.
SIGINT
:
[]
func
(){},
syscall
.
SIGTERM
:
[]
func
(){},
},
},
state
:
S
TATE_INIT
,
state
:
S
tateInit
,
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
)
...
...
grace/listener.go
View file @
65fb7ce3
...
...
@@ -11,10 +11,10 @@ type graceListener struct {
net
.
Listener
stop
chan
error
stopped
bool
server
*
grace
Server
server
*
Server
}
func
newGraceListener
(
l
net
.
Listener
,
srv
*
grace
Server
)
(
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
(
e
l
*
graceListener
)
Close
()
error
{
if
e
l
.
stopped
{
func
(
g
l
*
graceListener
)
Close
()
error
{
if
g
l
.
stopped
{
return
syscall
.
EINVAL
}
e
l
.
stop
<-
nil
return
<-
e
l
.
stop
g
l
.
stop
<-
nil
return
<-
g
l
.
stop
}
func
(
e
l
*
graceListener
)
File
()
*
os
.
File
{
func
(
g
l
*
graceListener
)
File
()
*
os
.
File
{
// returns a dup(2) - FD_CLOEXEC flag *not* set
tl
:=
e
l
.
Listener
.
(
*
net
.
TCPListener
)
tl
:=
g
l
.
Listener
.
(
*
net
.
TCPListener
)
fl
,
_
:=
tl
.
File
()
return
fl
}
grace/server.go
View file @
65fb7ce3
...
...
@@ -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
*
grace
Server
)
Serve
()
(
err
error
)
{
srv
.
state
=
S
TATE_RUNNING
func
(
srv
*
Server
)
Serve
()
(
err
error
)
{
srv
.
state
=
S
tateRunning
err
=
srv
.
Server
.
Serve
(
srv
.
GraceListener
)
log
.
Println
(
syscall
.
Getpid
(),
"Waiting for connections to finish..."
)
srv
.
wg
.
Wait
()
srv
.
state
=
S
TATE_TERMINATE
srv
.
state
=
S
tateTerminate
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
*
grace
Server
)
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
*
grace
Server
)
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
*
grace
Server
)
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
*
grace
Server
)
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
(
P
RE_SIGNAL
,
sig
)
srv
.
signalHooks
(
P
reSignal
,
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
(
P
OST_SIGNAL
,
sig
)
srv
.
signalHooks
(
P
ostSignal
,
sig
)
}
}
func
(
srv
*
grace
Server
)
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
*
grace
Server
)
shutdown
()
{
if
srv
.
state
!=
S
TATE_RUNNING
{
func
(
srv
*
Server
)
shutdown
()
{
if
srv
.
state
!=
S
tateRunning
{
return
}
srv
.
state
=
S
TATE_SHUTTING_DOWN
srv
.
state
=
S
tateShuttingDown
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
*
grace
Server
)
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
!=
S
TATE_SHUTTING_DOWN
{
if
srv
.
state
!=
S
tateShuttingDown
{
return
}
time
.
Sleep
(
d
)
log
.
Println
(
"[STOP - Hammer Time] Forcefully shutting down parent"
)
for
{
if
srv
.
state
==
S
TATE_TERMINATE
{
if
srv
.
state
==
S
tateTerminate
{
break
}
srv
.
wg
.
Done
()
}
}
func
(
srv
*
grace
Server
)
fork
()
(
err
error
)
{
func
(
srv
*
Server
)
fork
()
(
err
error
)
{
regLock
.
Lock
()
defer
regLock
.
Unlock
()
if
runningServersForked
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment