Asynchronous Execution

Asynchronous execution on dubbo provider side

The asynchronous execute on provider switches the blocked service from the internal thread pool of Dubbo to the service custom thread to avoid over-occupation of the Dubbo thread pool, which helps to avoid mutual influence between different services.Asynchronous-Execution is not conducive to saving resources or improving RPC responsiveness, because if business execution needs to be blocked, there is always a thread to be responsible for execution.

Interface that defines the CompletableFuture signature

Service interface definition:

public interface AsyncService {
    CompletableFuture<String> sayHello(String name);
}

Service implementation:

public class AsyncServiceImpl implements AsyncService {
    @Override
    public CompletableFuture<String> sayHello(String name) {
        RpcContext savedContext = RpcContext.getContext();
        // It is recommended to provide a custom thread pool for supplyAsync to avoid using the JDK common thread pool.
        return CompletableFuture.supplyAsync(() -> {
            System.out.println(savedContext.getAttachment("consumer-key1"));
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "async response from provider.";
        });
    }
}

The business execution has been switched from the Dubbo thread to the business thread by return CompletableFuture.supplyAsync(), avoiding blocking of the Dubbo thread pool.

Use AsyncContext

Dubbo provides an asynchronous interface AsyncContext similar to Serverlet 3.0. It can also implement asynchronous execution of the Provider without the CompletableFuture signature interface.

Service interface definition:

public interface AsyncService {
    String sayHello(String name);
}

Service export, exactly the same as ordinary service:

<bean id="asyncService" class="org.apache.dubbo.samples.governance.impl.AsyncServiceImpl"/>
<dubbo:service interface="org.apache.dubbo.samples.governance.api.AsyncService" ref="asyncService"/>

Service implementation:

public class AsyncServiceImpl implements AsyncService {
    public String sayHello(String name) {
        final AsyncContext asyncContext = RpcContext.startAsync();
        new Thread(() -> {
            // If you want to use context, you must do it at the very beginning
            asyncContext.signalContextSwitch();
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // Write to response
            asyncContext.write("Hello " + name + ", response from provider.");
        }).start();
        return null;
    }
}

Last modified November 25, 2020: fix sample code issue for SPI.md (#659) (0576d68)