aboutsummaryrefslogtreecommitdiff
path: root/server.go
diff options
context:
space:
mode:
authorGravatar Erik Dubbelboer <erik@dubbelboer.com> 2022-06-28 11:02:57 +0200
committerGravatar Erik Dubbelboer <erik@dubbelboer.com> 2022-06-28 11:04:21 +0200
commitb23c5e90838fdcb504032d8932c905ca7bd3b7ae (patch)
tree60553d8898207690ced21cf78984a359100e7778 /server.go
parentFix apparent documentation typo (#1330) (diff)
downloadfasthttp-b23c5e90838fdcb504032d8932c905ca7bd3b7ae.tar.gz
fasthttp-b23c5e90838fdcb504032d8932c905ca7bd3b7ae.tar.bz2
fasthttp-b23c5e90838fdcb504032d8932c905ca7bd3b7ae.zip
Close new connections after 5s in closeIdleConns
When calling closeIdleConns() also close new connections that haven't received any data within 5 seconds. Some applications open new connections but don't send anything and keep them as keep-alive for potential future requests. We don't want to keeping hanging on these when shutting down a server.
Diffstat (limited to 'server.go')
-rw-r--r--server.go26
1 files changed, 18 insertions, 8 deletions
diff --git a/server.go b/server.go
index 3c90455..6af2ed8 100644
--- a/server.go
+++ b/server.go
@@ -421,7 +421,7 @@ type Server struct {
// We need to know our listeners and idle connections so we can close them in Shutdown().
ln []net.Listener
- idleConns map[net.Conn]struct{}
+ idleConns map[net.Conn]time.Time
idleConnsMu sync.Mutex
mu sync.Mutex
@@ -1839,12 +1839,12 @@ func (s *Server) Shutdown() error {
close(s.done)
}
- s.closeIdleConns()
-
// Closing the listener will make Serve() call Stop on the worker pool.
// Setting .stop to 1 will make serveConn() break out of its loop.
// Now we just have to wait until all workers are done.
for {
+ s.closeIdleConns()
+
if open := atomic.LoadInt32(&s.open); open == 0 {
break
}
@@ -2816,9 +2816,16 @@ func (s *Server) trackConn(c net.Conn, state ConnState) {
switch state {
case StateIdle:
if s.idleConns == nil {
- s.idleConns = make(map[net.Conn]struct{})
+ s.idleConns = make(map[net.Conn]time.Time)
}
- s.idleConns[c] = struct{}{}
+ s.idleConns[c] = time.Now()
+ case StateNew:
+ if s.idleConns == nil {
+ s.idleConns = make(map[net.Conn]time.Time)
+ }
+ // Count the connection as Idle after 5 seconds.
+ // Same as net/http.Server: https://github.com/golang/go/blob/85d7bab91d9a3ed1f76842e4328973ea75efef54/src/net/http/server.go#L2834-L2836
+ s.idleConns[c] = time.Now().Add(time.Second * 5)
default:
delete(s.idleConns, c)
@@ -2828,10 +2835,13 @@ func (s *Server) trackConn(c net.Conn, state ConnState) {
func (s *Server) closeIdleConns() {
s.idleConnsMu.Lock()
- for c := range s.idleConns {
- _ = c.Close()
+ now := time.Now()
+ for c, t := range s.idleConns {
+ if now.Sub(t) >= 0 {
+ _ = c.Close()
+ delete(s.idleConns, c)
+ }
}
- s.idleConns = nil
s.idleConnsMu.Unlock()
}