Apache Dubbo is a powerful RPC framework for building enterprise-grade microservices with service discovery, load balancing, and fault tolerance.
—
Apache Dubbo's clustering system provides fault tolerance, load balancing, and traffic management capabilities across multiple service providers. It includes various cluster strategies, load balancing algorithms, routing rules, and provider directory management.
Cluster strategies define how to handle failures and distribute requests across multiple service providers.
/**
* Cluster interface for fault tolerance strategies
*/
@SPI(FailoverCluster.NAME)
public interface Cluster {
/**
* Join multiple invokers into a cluster
* @param directory Provider directory
* @return Cluster invoker
* @throws RpcException if cluster creation fails
*/
<T> Invoker<T> join(Directory<T> directory) throws RpcException;
}Built-in Cluster Implementations:
/**
* Failover cluster - automatically failover to other providers when failure occurs
*/
public class FailoverCluster implements Cluster {
public static final String NAME = "failover";
}
/**
* Failfast cluster - fail immediately on first error
*/
public class FailfastCluster implements Cluster {
public static final String NAME = "failfast";
}
/**
* Failsafe cluster - ignore failures and return empty result
*/
public class FailsafeCluster implements Cluster {
public static final String NAME = "failsafe";
}
/**
* Failback cluster - retry failed requests in background
*/
public class FailbackCluster implements Cluster {
public static final String NAME = "failback";
}
/**
* Broadcast cluster - broadcast invocation to all providers
*/
public class BroadcastCluster implements Cluster {
public static final String NAME = "broadcast";
}
/**
* Forking cluster - parallel invocation, return first successful result
*/
public class ForkingCluster implements Cluster {
public static final String NAME = "forking";
}
/**
* Available cluster - call the first available provider
*/
public class AvailableCluster implements Cluster {
public static final String NAME = "available";
}
/**
* Mergeable cluster - merge results from multiple providers
*/
public class MergeableCluster implements Cluster {
public static final String NAME = "mergeable";
}Usage Examples:
// Configure cluster strategy in service reference
ReferenceConfig<GreeterService> reference = new ReferenceConfig<>();
reference.setInterface(GreeterService.class);
reference.setCluster("failover"); // Use failover strategy
reference.setRetries(2); // Retry 2 times on failure
// Or configure via URL parameters
reference.setUrl("dubbo://localhost:20880/GreeterService?cluster=failfast");Load balancing algorithms distribute requests across available service providers.
/**
* Load balance interface for selecting providers
*/
@SPI(RandomLoadBalance.NAME)
public interface LoadBalance {
/**
* Select one invoker from available providers
* @param invokers Available service providers
* @param url Service URL with parameters
* @param invocation RPC invocation context
* @return Selected invoker
* @throws RpcException if selection fails
*/
<T> Invoker<T> select(List<Invoker<T>> invokers, URL url, Invocation invocation)
throws RpcException;
}Built-in Load Balance Implementations:
/**
* Random load balance - select provider randomly
*/
public class RandomLoadBalance extends AbstractLoadBalance {
public static final String NAME = "random";
@Override
protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {
// Implementation selects random provider
return invokers.get(ThreadLocalRandom.current().nextInt(invokers.size()));
}
}
/**
* Round robin load balance - weighted round-robin selection
*/
public class RoundRobinLoadBalance extends AbstractLoadBalance {
public static final String NAME = "roundrobin";
}
/**
* Least active load balance - select provider with least active requests
*/
public class LeastActiveLoadBalance extends AbstractLoadBalance {
public static final String NAME = "leastactive";
}
/**
* Shortest response load balance - select provider with shortest response time
*/
public class ShortestResponseLoadBalance extends AbstractLoadBalance {
public static final String NAME = "shortestresponse";
}
/**
* Consistent hash load balance - consistent hash ring selection
*/
public class ConsistentHashLoadBalance extends AbstractLoadBalance {
public static final String NAME = "consistenthash";
}
/**
* Adaptive load balance - select based on adaptive algorithm
*/
public class AdaptiveLoadBalance extends AbstractLoadBalance {
public static final String NAME = "adaptive";
}Usage Examples:
// Configure load balancing in service reference
ReferenceConfig<GreeterService> reference = new ReferenceConfig<>();
reference.setInterface(GreeterService.class);
reference.setLoadbalance("roundrobin"); // Use round-robin load balancing
// Configure per method
MethodConfig method = new MethodConfig();
method.setName("sayHello");
method.setLoadbalance("leastactive");
reference.setMethods(Arrays.asList(method));
// Configure consistent hash with specific hash arguments
reference.setUrl("dubbo://localhost:20880/GreeterService?loadbalance=consistenthash&hash.arguments=0");Directory interface manages the list of available service providers and handles provider changes.
/**
* Provider directory for managing service provider lists
* @param <T> Service interface type
*/
public interface Directory<T> {
/** Get service interface class */
Class<T> getInterface();
/**
* List available invokers for the invocation
* @param invocation RPC invocation context
* @return List of available invokers
* @throws RpcException if listing fails
*/
List<Invoker<T>> list(Invocation invocation) throws RpcException;
/** Get all invokers regardless of availability */
List<Invoker<T>> getAllInvokers();
/** Get directory URL */
URL getUrl();
/** Check if directory is destroyed */
boolean isDestroyed();
/** Destroy directory and release resources */
void destroy();
/** Get consumer URL */
URL getConsumerUrl();
}
/**
* Registry-aware directory that subscribes to provider changes
*/
public class RegistryDirectory<T> extends AbstractDirectory<T> implements NotifyListener {
public RegistryDirectory(Class<T> serviceType, URL url);
/** Subscribe to registry for provider updates */
public void subscribe(URL url);
/** Unsubscribe from registry */
public void unsubscribe(URL url);
/** Handle provider change notifications */
public void notify(List<URL> urls);
/** Refresh provider list */
protected void refreshInvoker(List<URL> invokerUrls);
}
/**
* Static directory with fixed provider list
*/
public class StaticDirectory<T> extends AbstractDirectory<T> {
public StaticDirectory(List<Invoker<T>> invokers);
public StaticDirectory(URL url, List<Invoker<T>> invokers);
}Routers filter and sort providers based on routing rules.
/**
* Router interface for filtering and sorting providers
*/
@SPI
public interface Router extends Comparable<Router> {
/** Get router URL */
URL getUrl();
/**
* Route providers based on rules
* @param invokers Available providers
* @param url Consumer URL
* @param invocation RPC invocation
* @return Filtered providers
* @throws RpcException if routing fails
*/
<T> List<Invoker<T>> route(List<Invoker<T>> invokers, URL url, Invocation invocation)
throws RpcException;
/** Check if routing is required for this invocation */
boolean isRuntime();
/** Check if router should be forced to execute */
boolean isForce();
/** Get router priority (lower value = higher priority) */
int getPriority();
}
/**
* Router chain for managing multiple routers
*/
public class RouterChain<T> {
public RouterChain(URL url);
/** Add router to chain */
public void addRouter(Router router);
/** Remove router from chain */
public void removeRouter(Router router);
/** Route through all routers in chain */
public List<Invoker<T>> route(URL url, Invocation invocation);
/** Set invokers for routing */
public void setInvokers(List<Invoker<T>> invokers);
}Built-in Router Types:
/**
* Condition router based on rules
*/
public class ConditionRouter implements Router {
public ConditionRouter(URL url);
/** Parse routing conditions */
protected void parseRule(String rule);
}
/**
* Script router using JavaScript expressions
*/
public class ScriptRouter implements Router {
public ScriptRouter(URL url);
}
/**
* File-based router loading rules from files
*/
public class FileRouter implements Router {
public FileRouter(URL url);
}
/**
* Tag router for routing based on request tags
*/
public class TagRouter implements Router {
public TagRouter(URL url);
}Usage Examples:
// Condition router rule examples
// Route requests with parameter "user" = "admin" to providers in group "admin"
String rule = "user = admin => group = admin";
// Route all requests during 9-17 hours to specific providers
String timeRule = "=> host = 192.168.1.10,192.168.1.11";
// Configure router in consumer
reference.setUrl("dubbo://localhost:20880/GreeterService?router=condition&rule=" +
URLEncoder.encode(rule, "UTF-8"));Configurators provide dynamic configuration changes for routing and load balancing.
/**
* Configurator interface for dynamic configuration
*/
@SPI
public interface Configurator extends Comparable<Configurator> {
/** Get configurator URL */
URL getUrl();
/**
* Configure URL with dynamic rules
* @param url Original URL
* @return Configured URL
*/
URL configure(URL url);
}
/**
* Factory for creating configurators
*/
@SPI("override")
public interface ConfiguratorFactory {
/**
* Create configurator from URL
* @param url Configuration URL
* @return Configurator instance
*/
Configurator getConfigurator(URL url);
}
/**
* Override configurator for parameter overrides
*/
public class OverrideConfigurator implements Configurator {
public OverrideConfigurator(URL url);
@Override
public URL configure(URL url) {
// Apply parameter overrides
return url.addParameters(getUrl().getParameters());
}
}
/**
* Absent configurator for conditional configuration
*/
public class AbsentConfigurator implements Configurator {
public AbsentConfigurator(URL url);
}Abstract base class for cluster invoker implementations.
/**
* Abstract cluster invoker providing common cluster functionality
* @param <T> Service interface type
*/
public abstract class AbstractClusterInvoker<T> implements Invoker<T> {
protected AbstractClusterInvoker(Directory<T> directory);
protected AbstractClusterInvoker(Directory<T> directory, URL url);
/** Get provider directory */
public Directory<T> getDirectory();
/** Get cluster URL */
public URL getUrl();
/** Check if invoker is available */
public boolean isAvailable();
/** Destroy cluster invoker */
public void destroy();
/**
* List available invokers with load balancing
* @param invocation RPC invocation
* @param loadbalance Load balance algorithm
* @return Selected invoker
* @throws RpcException if no invoker available
*/
protected List<Invoker<T>> list(Invocation invocation) throws RpcException;
/**
* Select invoker using load balance
* @param loadbalance Load balance algorithm
* @param invocation RPC invocation
* @param invokers Available invokers
* @param selected Previously selected invokers (for retry)
* @return Selected invoker
*/
protected Invoker<T> select(LoadBalance loadbalance, Invocation invocation,
List<Invoker<T>> invokers, List<Invoker<T>> selected)
throws RpcException;
/**
* Template method for cluster-specific invocation
* @param invocation RPC invocation
* @return Invocation result
* @throws RpcException if invocation fails
*/
protected abstract Result doInvoke(Invocation invocation, List<Invoker<T>> invokers,
LoadBalance loadbalance) throws RpcException;
}Configuration for sticky session support to ensure requests from the same client go to the same provider.
/**
* Sticky session management for consistent provider selection
*/
public class StickyUtils {
/**
* Get sticky invoker for the invocation
* @param invokers Available invokers
* @param invocation Current invocation
* @param stickyInvoker Previously selected sticky invoker
* @return Sticky invoker if available and sticky
*/
public static <T> Invoker<T> getSticky(List<Invoker<T>> invokers,
Invocation invocation,
Invoker<T> stickyInvoker) {
// Return sticky invoker if still available and sticky is enabled
if (stickyInvoker != null && invokers.contains(stickyInvoker) &&
isSticky(invocation)) {
return stickyInvoker;
}
return null;
}
/** Check if sticky session is enabled for invocation */
private static boolean isSticky(Invocation invocation) {
String sticky = invocation.getAttachment(STICKY_KEY);
return "true".equals(sticky);
}
}Usage Examples:
// Enable sticky sessions in service reference
ReferenceConfig<GreeterService> reference = new ReferenceConfig<>();
reference.setInterface(GreeterService.class);
reference.setSticky(true); // Enable sticky sessions
// Configure sticky per method
MethodConfig method = new MethodConfig();
method.setName("sayHello");
method.setSticky(true);
reference.setMethods(Arrays.asList(method));
// Set sticky attachment manually
RpcContext.getContext().setAttachment("sticky", "true");
String result = greeterService.sayHello("World");Configuration for fault tolerance behavior including timeouts, retries, and circuit breakers.
/**
* Constants for fault tolerance configuration
*/
public class ClusterConstants {
/** Cluster fault tolerance strategy */
public static final String CLUSTER_KEY = "cluster";
/** Load balance algorithm */
public static final String LOADBALANCE_KEY = "loadbalance";
/** Sticky session */
public static final String STICKY_KEY = "sticky";
/** Retry times */
public static final String RETRIES_KEY = "retries";
/** Fail strategy */
public static final String FAIL_KEY = "fail";
/** Fork count for forking cluster */
public static final String FORKS_KEY = "forks";
/** Default retry times */
public static final int DEFAULT_RETRIES = 2;
/** Default fork count */
public static final int DEFAULT_FORKS = 2;
}Usage Examples:
// Configure comprehensive fault tolerance
ReferenceConfig<GreeterService> reference = new ReferenceConfig<>();
reference.setInterface(GreeterService.class);
reference.setCluster("failover"); // Automatic failover
reference.setLoadbalance("roundrobin"); // Round-robin load balancing
reference.setRetries(3); // Retry 3 times on failure
reference.setTimeout(5000); // 5 second timeout
reference.setConnections(5); // 5 connections per provider
// Method-specific fault tolerance
MethodConfig criticalMethod = new MethodConfig();
criticalMethod.setName("processOrder");
criticalMethod.setCluster("failfast"); // Fail immediately for critical operations
criticalMethod.setTimeout(10000); // Longer timeout for critical operations
criticalMethod.setRetries(0); // No retries for critical operations
reference.setMethods(Arrays.asList(criticalMethod));Install with Tessl CLI
npx tessl i tessl/maven-org-apache-dubbo--dubbo