Asynchronous Calls

Dubbo not only provides traditional synchronous blocking call methods but also supports efficient asynchronous call patterns.

Asynchronous Call Implementation

Service Definition

public interface GreetingService {
    String sayHello(String name, int timeToWait);
}

Consumer Configuration

<dubbo:reference id="greetingService" interface="com.example.GreetingService">
    <dubbo:method name="sayHello" async="true" />
</dubbo:reference>

Consumer Call Example

// Initiate asynchronous call
greetingService.sayHello("world", 1000);

// Returns null immediately, actual call executes in background
System.out.println("Call returns immediately, continue executing other operations...");

// Get Future object from RpcContext
Future<String> future = RpcContext.getContext().getFuture();

// Wait and get result
String result = future.get(1500, TimeUnit.MILLISECONDS);

Notes

  1. Timeout Control: Dubbo’s default async call timeout is 1000ms
  2. Future Acquisition: Must obtain Future object in the same thread that initiated the call
  3. Exception Handling: Asynchronous calls need to check execution status and exceptions through Future

Thread Pool

Existing Thread Pool Implementations

1. Fixed size thread pool (fix)

  • This is the default thread pool implementation used by Dubbo
  • Creates 200 worker threads by default with no waiting queue
  • Thread count is fixed and will not dynamically increase or decrease

2. Cached thread pool (cache)

  • Thread count is not fixed and will be dynamically created based on demand
  • Idle threads will be recycled (default after 60 seconds)
  • Theoretically can infinitely expand thread count

Configuration Example

<dubbo:protocol name="dubbo" threadpool="fixed" threads="200"/>

Custom Thread Pool Solution

public class WzkWatchingThreadPool extends FixedThreadPool implements Runnable {
    private static final double ALARM_PERCENT = 0.9;
    private final Map<URL, ThreadPoolExecutor> THREADS_POOLS = new ConcurrentHashMap<>();

    @Override
    public Executor getExecutor(URL url) {
        final Executor executor = super.getExecutor(url);
        if (executor instanceof ThreadPoolExecutor) {
            THREADS_POOLS.put(url, (ThreadPoolExecutor) executor);
        }
        return executor;
    }

    @Override
    public void run() {
        // Monitor thread pool usage
    }
}

SPI Declaration

File META-INF/dubbo/org.apache.dubbo.common.threadpool.ThreadPool

wzkWatching=icu.wzk.pool.WzkWatchingThreadPool

Configuration Usage

dubbo.provider.threadpool=wzkWatching

Best Practices

  • Set independent thread pools for different businesses
  • Select appropriate thread pool type based on business characteristics
  • Establish a comprehensive monitoring and alerting system
  • Regularly perform pressure tests to evaluate thread pool capacity