graceful. not even mad
This commit is contained in:
parent
6c0386862a
commit
476a3bc84c
24
README
24
README
@ -33,12 +33,25 @@ gobyexample.com signups
|
|||||||
* updates forever
|
* updates forever
|
||||||
* no drm
|
* no drm
|
||||||
|
|
||||||
|
= sources
|
||||||
|
* effective go
|
||||||
|
* chinese web apps book
|
||||||
|
* http://news.ycombinator.com/item?id=4543818
|
||||||
|
|
||||||
= topics
|
= topics
|
||||||
|
* web app
|
||||||
|
* serve static files
|
||||||
|
* log requests
|
||||||
|
* basic auth
|
||||||
|
* force https
|
||||||
|
* force canonical host
|
||||||
|
* not found page
|
||||||
|
* error page
|
||||||
|
* graceful shutdown
|
||||||
|
* string formatting
|
||||||
|
* mongo
|
||||||
* worker pool
|
* worker pool
|
||||||
* rate limiting
|
* rate limiting
|
||||||
|
|
||||||
* string formatting
|
|
||||||
* web app
|
|
||||||
* time formatting
|
* time formatting
|
||||||
* typed json parse/unparse
|
* typed json parse/unparse
|
||||||
* gzip
|
* gzip
|
||||||
@ -52,7 +65,9 @@ gobyexample.com signups
|
|||||||
* oauth for google domains
|
* oauth for google domains
|
||||||
* testing
|
* testing
|
||||||
* markdown (blackfriday)
|
* markdown (blackfriday)
|
||||||
* mongo
|
* init functions
|
||||||
|
* using gofmt
|
||||||
|
* scrolls style logging
|
||||||
|
|
||||||
* setting up go env, hello world
|
* setting up go env, hello world
|
||||||
* deploying to heroku
|
* deploying to heroku
|
||||||
@ -66,3 +81,4 @@ command line client for public json api
|
|||||||
redis server
|
redis server
|
||||||
github webook receiver
|
github webook receiver
|
||||||
campfire bot
|
campfire bot
|
||||||
|
http://www.youtube.com/watch?v=-i0hat7pdpk
|
||||||
|
@ -49,3 +49,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
fmt.Println(area)
|
fmt.Println(area)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// == todo
|
||||||
|
// is this named wrong?
|
||||||
|
// note about embedding access
|
||||||
|
86
src/xx-http-server-graceful-shutdown.go
Normal file
86
src/xx-http-server-graceful-shutdown.go
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import ("net"; "net/http"; "time"; "os"; "os/signal"; "syscall"; "fmt"; "sync/atomic")
|
||||||
|
|
||||||
|
func slow(res http.ResponseWriter, req *http.Request) {
|
||||||
|
fmt.Println("respond at=start")
|
||||||
|
time.Sleep(time.Second * 5)
|
||||||
|
res.Header().Set("Content-Type", "text/plain")
|
||||||
|
fmt.Fprintln(res, "Finally.")
|
||||||
|
fmt.Println("respond at=finish")
|
||||||
|
}
|
||||||
|
|
||||||
|
var connCount int64 = 0
|
||||||
|
|
||||||
|
type watchedConn struct {
|
||||||
|
net.Conn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *watchedConn) Close() error {
|
||||||
|
atomic.AddInt64(&connCount, -1)
|
||||||
|
return w.Conn.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
type watchedListener struct {
|
||||||
|
net.Listener
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *watchedListener) Accept() (net.Conn, error) {
|
||||||
|
conn, err := l.Listener.Accept()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
atomic.AddInt64(&connCount, 1)
|
||||||
|
return &watchedConn{Conn: conn}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
stop := make(chan bool, 1)
|
||||||
|
sig := make(chan os.Signal, 1)
|
||||||
|
|
||||||
|
server := &http.Server{Handler: http.HandlerFunc(slow)}
|
||||||
|
fmt.Println("listen at=start")
|
||||||
|
listener, listenErr := net.Listen("tcp", ":5000")
|
||||||
|
if listenErr != nil { panic(listenErr) }
|
||||||
|
wListener := &watchedListener{Listener: listener}
|
||||||
|
fmt.Println("listen at=finish")
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
<-stop
|
||||||
|
fmt.Println("close at=start")
|
||||||
|
closeErr := wListener.Close()
|
||||||
|
if closeErr != nil { panic(closeErr) }
|
||||||
|
fmt.Println("close at=finish")
|
||||||
|
}()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
|
||||||
|
fmt.Println("trap at=start")
|
||||||
|
<- sig
|
||||||
|
stop <- true
|
||||||
|
fmt.Println("trap at=finish")
|
||||||
|
}()
|
||||||
|
|
||||||
|
fmt.Println("serve at=start")
|
||||||
|
server.Serve(wListener)
|
||||||
|
fmt.Println("serve at=finish")
|
||||||
|
for {
|
||||||
|
connCountCurrent := atomic.LoadInt64(&connCount)
|
||||||
|
if connCountCurrent > 0 {
|
||||||
|
fmt.Println("wait at=pending remaining=", connCountCurrent)
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
} else {
|
||||||
|
fmt.Println("wait at=finish remaining=", connCountCurrent)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// == running
|
||||||
|
// $ cd src
|
||||||
|
// $ go build xx-http-server-graceful-shutdown.go
|
||||||
|
// $ ./xx-http-server-graceful-shutdown
|
||||||
|
//
|
||||||
|
// $ curl -i http://127.0.0.1:5000/
|
||||||
|
//
|
||||||
|
// ^C
|
@ -7,7 +7,9 @@ consisting of more than a hundred complete Go programs. The book
|
|||||||
covers everything from getting started to writing sophisticated
|
covers everything from getting started to writing sophisticated
|
||||||
concurrent programs.
|
concurrent programs.
|
||||||
|
|
||||||
|
Sign up to hear when an early release is ready:
|
||||||
|
|
||||||
|
[ you@domain.com]
|
||||||
|
|
||||||
You'll learn the basic of Go and how to build real-world programs
|
You'll learn the basic of Go and how to build real-world programs
|
||||||
like database-backed web sites.
|
like database-backed web sites.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user