Client configuration APIs and shared utilities for Netflix's Ribbon IPC library, providing core interfaces for load balancing, fault tolerance, and service discovery capabilities in cloud environments.
—
Configurable retry logic with support for different exception types, circuit breaker patterns, and request-specific retry behavior. The retry system provides intelligent failure handling for distributed systems.
Core interface for determining if exceptions are retriable and circuit-related.
/**
* Interface for determining if exceptions are retriable and circuit-related
*/
public interface RetryHandler {
/**
* Default retry handler instance
*/
RetryHandler DEFAULT = new DefaultLoadBalancerRetryHandler();
/**
* Tests if exception is retriable
* @param e the exception to test
* @param sameServer true if retry should be on same server, false for different server
* @return true if the exception indicates the request can be retried
*/
boolean isRetriableException(Throwable e, boolean sameServer);
/**
* Tests if exception should trip circuit breaker
* @param e the exception to test
* @return true if this exception should cause the circuit breaker to open
*/
boolean isCircuitTrippingException(Throwable e);
/**
* Returns max retries on same server
* @return maximum number of retry attempts on the same server
*/
int getMaxRetriesOnSameServer();
/**
* Returns max retries on different servers
* @return maximum number of retry attempts on different servers
*/
int getMaxRetriesOnNextServer();
}Default retry handler implementation with support for common Java network exceptions.
/**
* Default retry handler implementation with support for common Java network exceptions
*/
public class DefaultLoadBalancerRetryHandler implements RetryHandler {
/**
* Creates retry handler with default settings
*/
public DefaultLoadBalancerRetryHandler();
/**
* Creates retry handler with specific retry counts
* @param retrySameServer maximum retries on same server
* @param retryNextServer maximum retries on different servers
* @param retryEnabled whether retry is enabled at all
*/
public DefaultLoadBalancerRetryHandler(int retrySameServer, int retryNextServer, boolean retryEnabled);
/**
* Creates retry handler from client configuration
* @param clientConfig configuration containing retry settings
*/
public DefaultLoadBalancerRetryHandler(IClientConfig clientConfig);
/**
* Tests if exception is retriable
* @param e the exception to test
* @param sameServer true if retry should be on same server
* @return true if the exception indicates the request can be retried
*/
public boolean isRetriableException(Throwable e, boolean sameServer);
/**
* Tests if exception should trip circuit breaker
* @param e the exception to test
* @return true if this exception should cause the circuit breaker to open
*/
public boolean isCircuitTrippingException(Throwable e);
/**
* Returns max retries on same server
* @return maximum number of retry attempts on the same server
*/
public int getMaxRetriesOnSameServer();
/**
* Returns max retries on different servers
* @return maximum number of retry attempts on different servers
*/
public int getMaxRetriesOnNextServer();
}Usage Examples:
import com.netflix.client.*;
import com.netflix.client.config.*;
// Default retry handler
RetryHandler defaultHandler = new DefaultLoadBalancerRetryHandler();
// Custom retry configuration
RetryHandler customHandler = new DefaultLoadBalancerRetryHandler(
3, // max retries on same server
2, // max retries on different servers
true // retry enabled
);
// Configuration-based retry handler
IClientConfig config = ClientConfigFactory.DEFAULT.newConfig();
config.set(CommonClientConfigKey.MaxAutoRetries, 3);
config.set(CommonClientConfigKey.MaxAutoRetriesNextServer, 1);
config.set(CommonClientConfigKey.OkToRetryOnAllOperations, false);
RetryHandler configHandler = new DefaultLoadBalancerRetryHandler(config);
// Using retry handler in client logic
public class MyClient {
private final RetryHandler retryHandler;
public MyClient(RetryHandler retryHandler) {
this.retryHandler = retryHandler;
}
public void handleRequest(ClientRequest request) {
int sameServerRetries = 0;
int nextServerRetries = 0;
while (true) {
try {
// Attempt request execution
executeRequest(request);
break; // Success
} catch (Exception e) {
boolean canRetrySameServer = sameServerRetries < retryHandler.getMaxRetriesOnSameServer()
&& retryHandler.isRetriableException(e, true);
boolean canRetryNextServer = nextServerRetries < retryHandler.getMaxRetriesOnNextServer()
&& retryHandler.isRetriableException(e, false);
if (canRetrySameServer) {
sameServerRetries++;
// Retry on same server
} else if (canRetryNextServer) {
nextServerRetries++;
// Retry on different server
} else {
// Check if should trip circuit breaker
if (retryHandler.isCircuitTrippingException(e)) {
// Trip circuit breaker
}
throw e; // No more retries
}
}
}
}
}Retry handler implementation created for each request allowing request-specific overrides.
/**
* Retry handler implementation created for each request allowing request-specific overrides
*/
public class RequestSpecificRetryHandler implements RetryHandler {
/**
* Creates request-specific retry handler
* @param okToRetryOnConnectErrors whether to retry on connection errors
* @param okToRetryOnAllErrors whether to retry on all types of errors
*/
public RequestSpecificRetryHandler(boolean okToRetryOnConnectErrors, boolean okToRetryOnAllErrors);
/**
* Creates request-specific retry handler with base handler
* @param okToRetryOnConnectErrors whether to retry on connection errors
* @param okToRetryOnAllErrors whether to retry on all types of errors
* @param baseRetryHandler base retry handler to delegate to
* @param requestConfig configuration for this specific request
*/
public RequestSpecificRetryHandler(boolean okToRetryOnConnectErrors, boolean okToRetryOnAllErrors,
RetryHandler baseRetryHandler, IClientConfig requestConfig);
/**
* Tests if exception is connection-related
* @param e the exception to test
* @return true if this is a connection-related exception
*/
public boolean isConnectionException(Throwable e);
/**
* Tests if exception is retriable
* @param e the exception to test
* @param sameServer true if retry should be on same server
* @return true if the exception indicates the request can be retried
*/
public boolean isRetriableException(Throwable e, boolean sameServer);
/**
* Tests if exception should trip circuit breaker
* @param e the exception to test
* @return true if this exception should cause the circuit breaker to open
*/
public boolean isCircuitTrippingException(Throwable e);
/**
* Returns max retries on same server
* @return maximum number of retry attempts on the same server
*/
public int getMaxRetriesOnSameServer();
/**
* Returns max retries on different servers
* @return maximum number of retry attempts on different servers
*/
public int getMaxRetriesOnNextServer();
}Advanced Usage Examples:
// Request-specific retry behavior
public class AdaptiveClient {
private final RetryHandler baseRetryHandler;
public AdaptiveClient(RetryHandler baseRetryHandler) {
this.baseRetryHandler = baseRetryHandler;
}
public void executeIdempotentRequest(ClientRequest request, IClientConfig config) {
// For idempotent requests, allow retries on all errors
RetryHandler requestHandler = new RequestSpecificRetryHandler(
true, // retry on connect errors
true, // retry on all errors (safe for idempotent operations)
baseRetryHandler,
config
);
executeWithRetry(request, config, requestHandler);
}
public void executeNonIdempotentRequest(ClientRequest request, IClientConfig config) {
// For non-idempotent requests, only retry on connection errors
RetryHandler requestHandler = new RequestSpecificRetryHandler(
true, // retry on connect errors
false, // don't retry on other errors (not safe for non-idempotent)
baseRetryHandler,
config
);
executeWithRetry(request, config, requestHandler);
}
private void executeWithRetry(ClientRequest request, IClientConfig config, RetryHandler handler) {
// Implementation using the specific retry handler
}
}
// Circuit breaker integration
public class CircuitBreakerAwareClient {
private volatile boolean circuitOpen = false;
private long circuitOpenTime = 0;
private final long circuitRecoveryTimeout = 30000; // 30 seconds
public void executeRequest(ClientRequest request, IClientConfig config) {
RetryHandler retryHandler = new DefaultLoadBalancerRetryHandler(config);
// Check circuit breaker state
if (circuitOpen) {
long now = System.currentTimeMillis();
if (now - circuitOpenTime > circuitRecoveryTimeout) {
circuitOpen = false; // Try to recover
} else {
throw new RuntimeException("Circuit breaker is open");
}
}
try {
// Execute request with retry logic
executeWithHandler(request, retryHandler);
} catch (Exception e) {
if (retryHandler.isCircuitTrippingException(e)) {
circuitOpen = true;
circuitOpenTime = System.currentTimeMillis();
}
throw e;
}
}
}The retry handlers classify exceptions into different categories for appropriate handling:
Retriable Exceptions (typically network-related):
ConnectException - Connection refused or failedSocketTimeoutException - Socket operation timed outNoRouteToHostException - No route to target hostCircuit Breaker Exceptions (indicate service issues):
SocketTimeoutException - May indicate service overloadConnectException - May indicate service downNon-Retriable Exceptions (client or business logic errors):
UnknownHostException - DNS resolution failureInstall with Tessl CLI
npx tessl i tessl/maven-com-netflix-ribbon--ribbon-core