in spectator-ext-sandbox/src/main/java/com/netflix/spectator/sandbox/HttpRequestBuilder.java [209:250]
public HttpResponse send() throws IOException {
HttpResponse response = null;
for (int attempt = 1; attempt <= numAttempts; ++attempt) {
entry.withAttempt(attempt);
try {
response = sendImpl();
int s = response.status();
if (s == 429 || s == 503) {
// Request is getting throttled, exponentially back off
// - 429 client sending too many requests
// - 503 server unavailable
try {
long delay = initialRetryDelay << (attempt - 1);
LOGGER.debug("request throttled, delaying for {}ms: {} {}", delay, method, uri);
Thread.sleep(delay);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IOException("request failed " + method + " " + uri, e);
}
} else if (s < 500) {
// 4xx errors other than 429 are not considered retriable, so for anything
// less than 500 just return the response to the user
return response;
}
} catch (IOException e) {
// All exceptions are considered retriable. Some like UnknownHostException are
// debatable, but we have seen them in some cases if there is a high latency for
// DNS lookups. So for now assume all exceptions are transient issues.
if (attempt == numAttempts) {
throw e;
} else {
LOGGER.warn("attempt {} of {} failed: {} {}", attempt, numAttempts, method, uri);
}
}
}
if (response == null) {
// Should not get here
throw new IOException("request failed " + method + " " + uri);
}
return response;
}