Add --request-timeout to allow the global request timeout of 60 seconds to be configured.
Kubernetes-commit: cb764756c6f152bfb866b161315369bc47ebf13c
This commit is contained in:
parent
d63053d0e4
commit
e1e8bebf50
|
@ -148,8 +148,11 @@ type Config struct {
|
||||||
// RESTOptionsGetter is used to construct RESTStorage types via the generic registry.
|
// RESTOptionsGetter is used to construct RESTStorage types via the generic registry.
|
||||||
RESTOptionsGetter genericregistry.RESTOptionsGetter
|
RESTOptionsGetter genericregistry.RESTOptionsGetter
|
||||||
|
|
||||||
// If specified, requests will be allocated a random timeout between this value, and twice this value.
|
// If specified, all requests except those which match the LongRunningFunc predicate will timeout
|
||||||
// Note that it is up to the request handlers to ignore or honor this timeout. In seconds.
|
// after this duration.
|
||||||
|
RequestTimeout time.Duration
|
||||||
|
// If specified, long running requests such as watch will be allocated a random timeout between this value, and
|
||||||
|
// twice this value. Note that it is up to the request handlers to ignore or honor this timeout. In seconds.
|
||||||
MinRequestTimeout int
|
MinRequestTimeout int
|
||||||
// MaxRequestsInFlight is the maximum number of parallel non-long-running requests. Every further
|
// MaxRequestsInFlight is the maximum number of parallel non-long-running requests. Every further
|
||||||
// request has to wait. Applies only to non-mutating requests.
|
// request has to wait. Applies only to non-mutating requests.
|
||||||
|
@ -222,6 +225,7 @@ func NewConfig(codecs serializer.CodecFactory) *Config {
|
||||||
EnableProfiling: true,
|
EnableProfiling: true,
|
||||||
MaxRequestsInFlight: 400,
|
MaxRequestsInFlight: 400,
|
||||||
MaxMutatingRequestsInFlight: 200,
|
MaxMutatingRequestsInFlight: 200,
|
||||||
|
RequestTimeout: time.Duration(60) * time.Second,
|
||||||
MinRequestTimeout: 1800,
|
MinRequestTimeout: 1800,
|
||||||
EnableAPIResponseCompression: utilfeature.DefaultFeatureGate.Enabled(features.APIResponseCompression),
|
EnableAPIResponseCompression: utilfeature.DefaultFeatureGate.Enabled(features.APIResponseCompression),
|
||||||
|
|
||||||
|
@ -477,7 +481,7 @@ func DefaultBuildHandlerChain(apiHandler http.Handler, c *Config) http.Handler {
|
||||||
}
|
}
|
||||||
handler = genericapifilters.WithAuthentication(handler, c.RequestContextMapper, c.Authenticator, genericapifilters.Unauthorized(c.RequestContextMapper, c.Serializer, c.SupportsBasicAuth))
|
handler = genericapifilters.WithAuthentication(handler, c.RequestContextMapper, c.Authenticator, genericapifilters.Unauthorized(c.RequestContextMapper, c.Serializer, c.SupportsBasicAuth))
|
||||||
handler = genericfilters.WithCORS(handler, c.CorsAllowedOriginList, nil, nil, nil, "true")
|
handler = genericfilters.WithCORS(handler, c.CorsAllowedOriginList, nil, nil, nil, "true")
|
||||||
handler = genericfilters.WithTimeoutForNonLongRunningRequests(handler, c.RequestContextMapper, c.LongRunningFunc)
|
handler = genericfilters.WithTimeoutForNonLongRunningRequests(handler, c.RequestContextMapper, c.LongRunningFunc, c.RequestTimeout)
|
||||||
handler = genericapifilters.WithRequestInfo(handler, NewRequestInfoResolver(c), c.RequestContextMapper)
|
handler = genericapifilters.WithRequestInfo(handler, NewRequestInfoResolver(c), c.RequestContextMapper)
|
||||||
handler = apirequest.WithRequestContext(handler, c.RequestContextMapper)
|
handler = apirequest.WithRequestContext(handler, c.RequestContextMapper)
|
||||||
handler = genericfilters.WithPanicRecovery(handler)
|
handler = genericfilters.WithPanicRecovery(handler)
|
||||||
|
|
|
@ -31,12 +31,10 @@ import (
|
||||||
apirequest "k8s.io/apiserver/pkg/endpoints/request"
|
apirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||||
)
|
)
|
||||||
|
|
||||||
const globalTimeout = time.Minute
|
|
||||||
|
|
||||||
var errConnKilled = fmt.Errorf("kill connection/stream")
|
var errConnKilled = fmt.Errorf("kill connection/stream")
|
||||||
|
|
||||||
// WithTimeoutForNonLongRunningRequests times out non-long-running requests after the time given by globalTimeout.
|
// WithTimeoutForNonLongRunningRequests times out non-long-running requests after the time given by timeout.
|
||||||
func WithTimeoutForNonLongRunningRequests(handler http.Handler, requestContextMapper apirequest.RequestContextMapper, longRunning apirequest.LongRunningRequestCheck) http.Handler {
|
func WithTimeoutForNonLongRunningRequests(handler http.Handler, requestContextMapper apirequest.RequestContextMapper, longRunning apirequest.LongRunningRequestCheck, timeout time.Duration) http.Handler {
|
||||||
if longRunning == nil {
|
if longRunning == nil {
|
||||||
return handler
|
return handler
|
||||||
}
|
}
|
||||||
|
@ -45,13 +43,13 @@ func WithTimeoutForNonLongRunningRequests(handler http.Handler, requestContextMa
|
||||||
ctx, ok := requestContextMapper.Get(req)
|
ctx, ok := requestContextMapper.Get(req)
|
||||||
if !ok {
|
if !ok {
|
||||||
// if this happens, the handler chain isn't setup correctly because there is no context mapper
|
// if this happens, the handler chain isn't setup correctly because there is no context mapper
|
||||||
return time.After(globalTimeout), func() {}, apierrors.NewInternalError(fmt.Errorf("no context found for request during timeout"))
|
return time.After(timeout), func() {}, apierrors.NewInternalError(fmt.Errorf("no context found for request during timeout"))
|
||||||
}
|
}
|
||||||
|
|
||||||
requestInfo, ok := apirequest.RequestInfoFrom(ctx)
|
requestInfo, ok := apirequest.RequestInfoFrom(ctx)
|
||||||
if !ok {
|
if !ok {
|
||||||
// if this happens, the handler chain isn't setup correctly because there is no request info
|
// if this happens, the handler chain isn't setup correctly because there is no request info
|
||||||
return time.After(globalTimeout), func() {}, apierrors.NewInternalError(fmt.Errorf("no request info found for request during timeout"))
|
return time.After(timeout), func() {}, apierrors.NewInternalError(fmt.Errorf("no request info found for request during timeout"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if longRunning(req, requestInfo) {
|
if longRunning(req, requestInfo) {
|
||||||
|
@ -69,7 +67,7 @@ func WithTimeoutForNonLongRunningRequests(handler http.Handler, requestContextMa
|
||||||
metrics.MonitorRequest(req, strings.ToUpper(requestInfo.Verb), "", requestInfo.Path, "", scope, http.StatusGatewayTimeout, 0, now)
|
metrics.MonitorRequest(req, strings.ToUpper(requestInfo.Verb), "", requestInfo.Path, "", scope, http.StatusGatewayTimeout, 0, now)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return time.After(globalTimeout), metricFn, apierrors.NewTimeoutError(fmt.Sprintf("request did not complete within %s", globalTimeout), 0)
|
return time.After(timeout), metricFn, apierrors.NewTimeoutError(fmt.Sprintf("request did not complete within %s", timeout), 0)
|
||||||
}
|
}
|
||||||
return WithTimeout(handler, timeoutFunc)
|
return WithTimeout(handler, timeoutFunc)
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ package options
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"time"
|
||||||
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||||
|
@ -39,6 +40,7 @@ type ServerRunOptions struct {
|
||||||
ExternalHost string
|
ExternalHost string
|
||||||
MaxRequestsInFlight int
|
MaxRequestsInFlight int
|
||||||
MaxMutatingRequestsInFlight int
|
MaxMutatingRequestsInFlight int
|
||||||
|
RequestTimeout time.Duration
|
||||||
MinRequestTimeout int
|
MinRequestTimeout int
|
||||||
TargetRAMMB int
|
TargetRAMMB int
|
||||||
WatchCacheSizes []string
|
WatchCacheSizes []string
|
||||||
|
@ -49,6 +51,7 @@ func NewServerRunOptions() *ServerRunOptions {
|
||||||
return &ServerRunOptions{
|
return &ServerRunOptions{
|
||||||
MaxRequestsInFlight: defaults.MaxRequestsInFlight,
|
MaxRequestsInFlight: defaults.MaxRequestsInFlight,
|
||||||
MaxMutatingRequestsInFlight: defaults.MaxMutatingRequestsInFlight,
|
MaxMutatingRequestsInFlight: defaults.MaxMutatingRequestsInFlight,
|
||||||
|
RequestTimeout: defaults.RequestTimeout,
|
||||||
MinRequestTimeout: defaults.MinRequestTimeout,
|
MinRequestTimeout: defaults.MinRequestTimeout,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,6 +62,7 @@ func (s *ServerRunOptions) ApplyTo(c *server.Config) error {
|
||||||
c.ExternalAddress = s.ExternalHost
|
c.ExternalAddress = s.ExternalHost
|
||||||
c.MaxRequestsInFlight = s.MaxRequestsInFlight
|
c.MaxRequestsInFlight = s.MaxRequestsInFlight
|
||||||
c.MaxMutatingRequestsInFlight = s.MaxMutatingRequestsInFlight
|
c.MaxMutatingRequestsInFlight = s.MaxMutatingRequestsInFlight
|
||||||
|
c.RequestTimeout = s.RequestTimeout
|
||||||
c.MinRequestTimeout = s.MinRequestTimeout
|
c.MinRequestTimeout = s.MinRequestTimeout
|
||||||
c.PublicAddress = s.AdvertiseAddress
|
c.PublicAddress = s.AdvertiseAddress
|
||||||
|
|
||||||
|
@ -93,7 +97,11 @@ func (s *ServerRunOptions) Validate() []error {
|
||||||
errors = append(errors, fmt.Errorf("--max-requests-inflight can not be negative value"))
|
errors = append(errors, fmt.Errorf("--max-requests-inflight can not be negative value"))
|
||||||
}
|
}
|
||||||
if s.MaxMutatingRequestsInFlight < 0 {
|
if s.MaxMutatingRequestsInFlight < 0 {
|
||||||
errors = append(errors, fmt.Errorf("--min-request-timeout can not be negative value"))
|
errors = append(errors, fmt.Errorf("--max-mutating-requests-inflight can not be negative value"))
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.RequestTimeout.Nanoseconds() < 0 {
|
||||||
|
errors = append(errors, fmt.Errorf("--request-timeout can not be negative value"))
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors
|
return errors
|
||||||
|
@ -132,6 +140,11 @@ func (s *ServerRunOptions) AddUniversalFlags(fs *pflag.FlagSet) {
|
||||||
"The maximum number of mutating requests in flight at a given time. When the server exceeds this, "+
|
"The maximum number of mutating requests in flight at a given time. When the server exceeds this, "+
|
||||||
"it rejects requests. Zero for no limit.")
|
"it rejects requests. Zero for no limit.")
|
||||||
|
|
||||||
|
fs.DurationVar(&s.RequestTimeout, "request-timeout", s.RequestTimeout, ""+
|
||||||
|
"An optional field indicating the duration a handler must keep a request open before timing "+
|
||||||
|
"it out. This is the default request timeout for requests but may be overridden by flags such as "+
|
||||||
|
"--min-request-timeout for specific types of requests.")
|
||||||
|
|
||||||
fs.IntVar(&s.MinRequestTimeout, "min-request-timeout", s.MinRequestTimeout, ""+
|
fs.IntVar(&s.MinRequestTimeout, "min-request-timeout", s.MinRequestTimeout, ""+
|
||||||
"An optional field indicating the minimum number of seconds a handler must keep "+
|
"An optional field indicating the minimum number of seconds a handler must keep "+
|
||||||
"a request open before timing it out. Currently only honored by the watch request "+
|
"a request open before timing it out. Currently only honored by the watch request "+
|
||||||
|
|
Loading…
Reference in New Issue