mirror of
https://github.com/kubernetes/client-go.git
synced 2025-06-28 07:57:20 +00:00
Merge pull request #99079 from tkashem/throttle-message
add more context to client-go request throttling message Kubernetes-commit: 83e140125c96bf9dbde46f4c13ebccb3909951cc
This commit is contained in:
commit
21dd7eaeef
@ -577,7 +577,7 @@ func (r Request) finalURLTemplate() url.URL {
|
|||||||
return *url
|
return *url
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Request) tryThrottle(ctx context.Context) error {
|
func (r *Request) tryThrottleWithInfo(ctx context.Context, retryInfo string) error {
|
||||||
if r.rateLimiter == nil {
|
if r.rateLimiter == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -587,19 +587,32 @@ func (r *Request) tryThrottle(ctx context.Context) error {
|
|||||||
err := r.rateLimiter.Wait(ctx)
|
err := r.rateLimiter.Wait(ctx)
|
||||||
|
|
||||||
latency := time.Since(now)
|
latency := time.Since(now)
|
||||||
|
|
||||||
|
var message string
|
||||||
|
switch {
|
||||||
|
case len(retryInfo) > 0:
|
||||||
|
message = fmt.Sprintf("Waited for %v, %s - request: %s:%s", latency, retryInfo, r.verb, r.URL().String())
|
||||||
|
default:
|
||||||
|
message = fmt.Sprintf("Waited for %v due to client-side throttling, not priority and fairness, request: %s:%s", latency, r.verb, r.URL().String())
|
||||||
|
}
|
||||||
|
|
||||||
if latency > longThrottleLatency {
|
if latency > longThrottleLatency {
|
||||||
klog.V(3).Infof("Throttling request took %v, request: %s:%s", latency, r.verb, r.URL().String())
|
klog.V(3).Info(message)
|
||||||
}
|
}
|
||||||
if latency > extraLongThrottleLatency {
|
if latency > extraLongThrottleLatency {
|
||||||
// If the rate limiter latency is very high, the log message should be printed at a higher log level,
|
// If the rate limiter latency is very high, the log message should be printed at a higher log level,
|
||||||
// but we use a throttled logger to prevent spamming.
|
// but we use a throttled logger to prevent spamming.
|
||||||
globalThrottledLogger.Infof("Throttling request took %v, request: %s:%s", latency, r.verb, r.URL().String())
|
globalThrottledLogger.Infof(message)
|
||||||
}
|
}
|
||||||
metrics.RateLimiterLatency.Observe(r.verb, r.finalURLTemplate(), latency)
|
metrics.RateLimiterLatency.Observe(r.verb, r.finalURLTemplate(), latency)
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Request) tryThrottle(ctx context.Context) error {
|
||||||
|
return r.tryThrottleWithInfo(ctx, "")
|
||||||
|
}
|
||||||
|
|
||||||
type throttleSettings struct {
|
type throttleSettings struct {
|
||||||
logLevel klog.Level
|
logLevel klog.Level
|
||||||
minLogInterval time.Duration
|
minLogInterval time.Duration
|
||||||
@ -869,6 +882,7 @@ func (r *Request) request(ctx context.Context, fn func(*http.Request, *http.Resp
|
|||||||
|
|
||||||
// Right now we make about ten retry attempts if we get a Retry-After response.
|
// Right now we make about ten retry attempts if we get a Retry-After response.
|
||||||
retries := 0
|
retries := 0
|
||||||
|
var retryInfo string
|
||||||
for {
|
for {
|
||||||
|
|
||||||
url := r.URL().String()
|
url := r.URL().String()
|
||||||
@ -884,9 +898,10 @@ func (r *Request) request(ctx context.Context, fn func(*http.Request, *http.Resp
|
|||||||
// We are retrying the request that we already send to apiserver
|
// We are retrying the request that we already send to apiserver
|
||||||
// at least once before.
|
// at least once before.
|
||||||
// This request should also be throttled with the client-internal rate limiter.
|
// This request should also be throttled with the client-internal rate limiter.
|
||||||
if err := r.tryThrottle(ctx); err != nil {
|
if err := r.tryThrottleWithInfo(ctx, retryInfo); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
retryInfo = ""
|
||||||
}
|
}
|
||||||
resp, err := client.Do(req)
|
resp, err := client.Do(req)
|
||||||
updateURLMetrics(r, resp, err)
|
updateURLMetrics(r, resp, err)
|
||||||
@ -931,6 +946,7 @@ func (r *Request) request(ctx context.Context, fn func(*http.Request, *http.Resp
|
|||||||
|
|
||||||
retries++
|
retries++
|
||||||
if seconds, wait := checkWait(resp); wait && retries <= r.maxRetries {
|
if seconds, wait := checkWait(resp); wait && retries <= r.maxRetries {
|
||||||
|
retryInfo = getRetryReason(retries, seconds, resp, err)
|
||||||
if seeker, ok := r.body.(io.Seeker); ok && r.body != nil {
|
if seeker, ok := r.body.(io.Seeker); ok && r.body != nil {
|
||||||
_, err := seeker.Seek(0, 0)
|
_, err := seeker.Seek(0, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1204,6 +1220,26 @@ func retryAfterSeconds(resp *http.Response) (int, bool) {
|
|||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getRetryReason(retries, seconds int, resp *http.Response, err error) string {
|
||||||
|
// priority and fairness sets the UID of the FlowSchema associated with a request
|
||||||
|
// in the following response Header.
|
||||||
|
const responseHeaderMatchedFlowSchemaUID = "X-Kubernetes-PF-FlowSchema-UID"
|
||||||
|
|
||||||
|
message := fmt.Sprintf("retries: %d, retry-after: %ds", retries, seconds)
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case resp.StatusCode == http.StatusTooManyRequests:
|
||||||
|
// it is server-side throttling from priority and fairness
|
||||||
|
flowSchemaUID := resp.Header.Get(responseHeaderMatchedFlowSchemaUID)
|
||||||
|
return fmt.Sprintf("%s - retry-reason: due to server-side throttling, FlowSchema UID: %q", message, flowSchemaUID)
|
||||||
|
case err != nil:
|
||||||
|
// it's a retriable error
|
||||||
|
return fmt.Sprintf("%s - retry-reason: due to retriable error, error: %v", message, err)
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("%s - retry-reason: %d", message, resp.StatusCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Result contains the result of calling Request.Do().
|
// Result contains the result of calling Request.Do().
|
||||||
type Result struct {
|
type Result struct {
|
||||||
body []byte
|
body []byte
|
||||||
|
Loading…
Reference in New Issue
Block a user