@@ -219,7 +219,7 @@ type Server struct {
219
219
220
220
concurrencyCh chan struct {}
221
221
222
- idleConns map [net.Conn ]time. Time
222
+ idleConns map [net.Conn ]* atomic. Int64
223
223
done chan struct {}
224
224
225
225
// Server name for sending in response headers.
@@ -2132,6 +2132,26 @@ func (s *Server) serveConn(c net.Conn) (err error) {
2132
2132
return handler (c )
2133
2133
}
2134
2134
2135
+ s .idleConnsMu .Lock ()
2136
+ if s .idleConns == nil {
2137
+ s .idleConns = make (map [net.Conn ]* atomic.Int64 )
2138
+ }
2139
+ idleConnTime , ok := s .idleConns [c ]
2140
+ if ! ok {
2141
+ v := idleConnTimePool .Get ()
2142
+ if v == nil {
2143
+ v = & atomic.Int64 {}
2144
+ }
2145
+ idleConnTime = v .(* atomic.Int64 )
2146
+ s .idleConns [c ] = idleConnTime
2147
+ }
2148
+
2149
+ // Count the connection as Idle after 5 seconds.
2150
+ // Same as net/http.Server:
2151
+ // https://github.com/golang/go/blob/85d7bab91d9a3ed1f76842e4328973ea75efef54/src/net/http/server.go#L2834-L2836
2152
+ idleConnTime .Store (time .Now ().Add (time .Second * 5 ).Unix ())
2153
+ s .idleConnsMu .Unlock ()
2154
+
2135
2155
serverName := s .getServerName ()
2136
2156
connRequestNum := uint64 (0 )
2137
2157
connID := nextConnID ()
@@ -2207,6 +2227,8 @@ func (s *Server) serveConn(c net.Conn) (err error) {
2207
2227
if err == nil {
2208
2228
s .setState (c , StateActive )
2209
2229
2230
+ idleConnTime .Store (0 )
2231
+
2210
2232
if s .ReadTimeout > 0 {
2211
2233
if err = c .SetReadDeadline (time .Now ().Add (s .ReadTimeout )); err != nil {
2212
2234
break
@@ -2485,6 +2507,8 @@ func (s *Server) serveConn(c net.Conn) (err error) {
2485
2507
err = nil
2486
2508
break
2487
2509
}
2510
+
2511
+ idleConnTime .Store (time .Now ().Unix ())
2488
2512
}
2489
2513
2490
2514
if br != nil {
@@ -2497,11 +2521,18 @@ func (s *Server) serveConn(c net.Conn) (err error) {
2497
2521
s .releaseCtx (ctx )
2498
2522
}
2499
2523
2524
+ s .idleConnsMu .Lock ()
2525
+ ic , ok := s .idleConns [c ]
2526
+ if ok {
2527
+ idleConnTimePool .Put (ic )
2528
+ delete (s .idleConns , c )
2529
+ }
2530
+ s .idleConnsMu .Unlock ()
2531
+
2500
2532
return
2501
2533
}
2502
2534
2503
2535
func (s * Server ) setState (nc net.Conn , state ConnState ) {
2504
- s .trackConn (nc , state )
2505
2536
if hook := s .ConnState ; hook != nil {
2506
2537
hook (nc , state )
2507
2538
}
@@ -2878,36 +2909,17 @@ func (s *Server) writeErrorResponse(bw *bufio.Writer, ctx *RequestCtx, serverNam
2878
2909
return bw
2879
2910
}
2880
2911
2881
- func (s * Server ) trackConn (c net.Conn , state ConnState ) {
2882
- s .idleConnsMu .Lock ()
2883
- switch state {
2884
- case StateIdle :
2885
- if s .idleConns == nil {
2886
- s .idleConns = make (map [net.Conn ]time.Time )
2887
- }
2888
- s .idleConns [c ] = time .Now ()
2889
- case StateNew :
2890
- if s .idleConns == nil {
2891
- s .idleConns = make (map [net.Conn ]time.Time )
2892
- }
2893
- // Count the connection as Idle after 5 seconds.
2894
- // Same as net/http.Server:
2895
- // https://github.com/golang/go/blob/85d7bab91d9a3ed1f76842e4328973ea75efef54/src/net/http/server.go#L2834-L2836
2896
- s .idleConns [c ] = time .Now ().Add (time .Second * 5 )
2897
-
2898
- default :
2899
- delete (s .idleConns , c )
2900
- }
2901
- s .idleConnsMu .Unlock ()
2902
- }
2912
+ var idleConnTimePool sync.Pool
2903
2913
2904
2914
func (s * Server ) closeIdleConns () {
2905
2915
s .idleConnsMu .Lock ()
2906
- now := time .Now ()
2907
- for c , t := range s .idleConns {
2908
- if now .Sub (t ) >= 0 {
2916
+ now := time .Now ().Unix ()
2917
+ for c , ict := range s .idleConns {
2918
+ t := ict .Load ()
2919
+ if t != 0 && now - t >= 0 {
2909
2920
_ = c .Close ()
2910
2921
delete (s .idleConns , c )
2922
+ idleConnTimePool .Put (ict )
2911
2923
}
2912
2924
}
2913
2925
s .idleConnsMu .Unlock ()
0 commit comments