k8s.io/apiserver@v0.31.1/pkg/server/filters/goaway.go (about) 1 /* 2 Copyright 2020 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package filters 18 19 import ( 20 "math/rand" 21 "net/http" 22 "sync" 23 ) 24 25 // GoawayDecider decides if server should send a GOAWAY 26 type GoawayDecider interface { 27 Goaway(r *http.Request) bool 28 } 29 30 var ( 31 // randPool used to get a rand.Rand and generate a random number thread-safely, 32 // which improve the performance of using rand.Rand with a locker 33 randPool = &sync.Pool{ 34 New: func() interface{} { 35 return rand.New(rand.NewSource(rand.Int63())) 36 }, 37 } 38 ) 39 40 // WithProbabilisticGoaway returns an http.Handler that send GOAWAY probabilistically 41 // according to the given chance for HTTP2 requests. After client receive GOAWAY, 42 // the in-flight long-running requests will not be influenced, and the new requests 43 // will use a new TCP connection to re-balancing to another server behind the load balance. 44 func WithProbabilisticGoaway(inner http.Handler, chance float64) http.Handler { 45 return &goaway{ 46 handler: inner, 47 decider: &probabilisticGoawayDecider{ 48 chance: chance, 49 next: func() float64 { 50 rnd := randPool.Get().(*rand.Rand) 51 ret := rnd.Float64() 52 randPool.Put(rnd) 53 return ret 54 }, 55 }, 56 } 57 } 58 59 // goaway send a GOAWAY to client according to decider for HTTP2 requests 60 type goaway struct { 61 handler http.Handler 62 decider GoawayDecider 63 } 64 65 // ServeHTTP implement HTTP handler 66 func (h *goaway) ServeHTTP(w http.ResponseWriter, r *http.Request) { 67 if r.Proto == "HTTP/2.0" && h.decider.Goaway(r) { 68 // Send a GOAWAY and tear down the TCP connection when idle. 69 w.Header().Set("Connection", "close") 70 } 71 72 h.handler.ServeHTTP(w, r) 73 } 74 75 // probabilisticGoawayDecider send GOAWAY probabilistically according to chance 76 type probabilisticGoawayDecider struct { 77 chance float64 78 next func() float64 79 } 80 81 // Goaway implement GoawayDecider 82 func (p *probabilisticGoawayDecider) Goaway(r *http.Request) bool { 83 return p.next() < p.chance 84 }