fix: timeout not working if greater than global rest timeout (#2926)

master
Kevin Wan 2 years ago committed by GitHub
parent ace125f189
commit 238c830f17
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -25,8 +25,10 @@ const topCpuUsage = 1000
var ErrSignatureConfig = errors.New("bad config for Signature") var ErrSignatureConfig = errors.New("bad config for Signature")
type engine struct { type engine struct {
conf RestConf conf RestConf
routes []featuredRoutes routes []featuredRoutes
// timeout is the max timeout of all routes
timeout time.Duration
unauthorizedCallback handler.UnauthorizedCallback unauthorizedCallback handler.UnauthorizedCallback
unsignedCallback handler.UnsignedCallback unsignedCallback handler.UnsignedCallback
chain chain.Chain chain chain.Chain
@ -38,8 +40,10 @@ type engine struct {
func newEngine(c RestConf) *engine { func newEngine(c RestConf) *engine {
svr := &engine{ svr := &engine{
conf: c, conf: c,
timeout: time.Duration(c.Timeout) * time.Millisecond,
} }
if c.CpuThreshold > 0 { if c.CpuThreshold > 0 {
svr.shedder = load.NewAdaptiveShedder(load.WithCpuThreshold(c.CpuThreshold)) svr.shedder = load.NewAdaptiveShedder(load.WithCpuThreshold(c.CpuThreshold))
svr.priorityShedder = load.NewAdaptiveShedder(load.WithCpuThreshold( svr.priorityShedder = load.NewAdaptiveShedder(load.WithCpuThreshold(
@ -51,6 +55,12 @@ func newEngine(c RestConf) *engine {
func (ng *engine) addRoutes(r featuredRoutes) { func (ng *engine) addRoutes(r featuredRoutes) {
ng.routes = append(ng.routes, r) ng.routes = append(ng.routes, r)
// need to guarantee the timeout is the max of all routes
// otherwise impossible to set http.Server.ReadTimeout & WriteTimeout
if r.timeout > ng.timeout {
ng.timeout = r.timeout
}
} }
func (ng *engine) appendAuthHandler(fr featuredRoutes, chn chain.Chain, func (ng *engine) appendAuthHandler(fr featuredRoutes, chn chain.Chain,
@ -314,15 +324,15 @@ func (ng *engine) use(middleware Middleware) {
func (ng *engine) withTimeout() internal.StartOption { func (ng *engine) withTimeout() internal.StartOption {
return func(svr *http.Server) { return func(svr *http.Server) {
timeout := ng.conf.Timeout timeout := ng.timeout
if timeout > 0 { if timeout > 0 {
// factor 0.8, to avoid clients send longer content-length than the actual content, // factor 0.8, to avoid clients send longer content-length than the actual content,
// without this timeout setting, the server will time out and respond 503 Service Unavailable, // without this timeout setting, the server will time out and respond 503 Service Unavailable,
// which triggers the circuit breaker. // which triggers the circuit breaker.
svr.ReadTimeout = 4 * time.Duration(timeout) * time.Millisecond / 5 svr.ReadTimeout = 4 * timeout / 5
// factor 1.1, to avoid servers don't have enough time to write responses. // factor 1.1, to avoid servers don't have enough time to write responses.
// setting the factor less than 1.0 may lead clients not receiving the responses. // setting the factor less than 1.0 may lead clients not receiving the responses.
svr.WriteTimeout = 11 * time.Duration(timeout) * time.Millisecond / 10 svr.WriteTimeout = 11 * timeout / 10
} }
} }
} }

@ -43,6 +43,7 @@ Verbose: true
Path: "/", Path: "/",
Handler: func(w http.ResponseWriter, r *http.Request) {}, Handler: func(w http.ResponseWriter, r *http.Request) {},
}}, }},
timeout: time.Minute,
}, },
{ {
priority: true, priority: true,
@ -53,6 +54,7 @@ Verbose: true
Path: "/", Path: "/",
Handler: func(w http.ResponseWriter, r *http.Request) {}, Handler: func(w http.ResponseWriter, r *http.Request) {},
}}, }},
timeout: time.Second,
}, },
{ {
priority: true, priority: true,
@ -159,6 +161,11 @@ Verbose: true
} }
}) })
assert.NotNil(t, ng.start(mockedRouter{})) assert.NotNil(t, ng.start(mockedRouter{}))
timeout := time.Second * 3
if route.timeout > timeout {
timeout = route.timeout
}
assert.Equal(t, timeout, ng.timeout)
} }
} }
} }

Loading…
Cancel
Save