Apache Dubbo服务提供者异步
- Apache Dubbo在新版加入了服务提供者异步
- 服务提供者异步在提升性能和响应时长没有任何用处
- 服务提供者异步旨在尽量规避Dubbo任务处理的瓶颈
图示:
代码演示
provider端接口实现
public class ServiceDemoImpl implements ServiceDemo {
private Executor executor = new ThreadPoolExecutor(2, 4, 1,
TimeUnit.MINUTES, new ArrayBlockingQueue<>(1000), new NamedThreadFactory("wwy-"),
new ThreadPoolExecutor.CallerRunsPolicy());
/**
* dubbo 高级特性之 异步执行
* @param context
* @return
*/
@Override
public String getSelf(String context) {
AsyncContext asyncContext = RpcContext.startAsync();
executor.execute(() -> {
//使得当前的子线程也可以使用rpc中的context信息
asyncContext.signalContextSwitch();
String result = "Provider response : Hello " + context + ", Thread name is " + Thread.currentThread().getName();
asyncContext.write(result);
});
return null;
}
}
consumer端dubbo调用
@SpringBootApplication
@ImportResource(locations = {"classpath:springContext-dubbo.xml"})
public class DubboDemoApplication {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ConfigurableApplicationContext context = SpringApplication.run(DubboDemoApplication.class, args);
ServiceDemo serviceDemo = context.getBean("serviceDemo", ServiceDemo.class);
//调用
String result = serviceDemo.getSelf("hello wwy");
System.out.println(result);
}
}
输出结果:
onReturn : Provider response : Hello hello wwy, Thread name is wwy--thread-1
源码解析
//org.apache.dubbo.rpc.RpcContext#startAsync
public static AsyncContext startAsync() throws IllegalStateException {
//先获取当前上下文
RpcContext currentContext = getContext();
//如果不存在asyncContext 则创建并赋值
if (currentContext.asyncContext == null) {
currentContext.asyncContext = new AsyncContextImpl();
}
//开启
currentContext.asyncContext.start();
return currentContext.asyncContext;
}
public AsyncContextImpl() {
//保存rpc的基本信息到该对象中
this.storedContext = RpcContext.getContext();
this.storedServerContext = RpcContext.getServerContext();
}
@Override
public void start() {
//创建CompletableFuture
if (this.started.compareAndSet(false, true)) {
this.future = new CompletableFuture<>();
}
}
@Override
public void signalContextSwitch() {
RpcContext.restoreContext(storedContext);
RpcContext.restoreServerContext(storedServerContext);
// Restore any other contexts in here if necessary.
}
@Override
public void write(Object value) {
//判断是否已开启,并且设置为停止状态成功
if (isAsyncStarted() && stop()) {
if (value instanceof Throwable) {
Throwable bizExe = (Throwable) value;
future.completeExceptionally(bizExe);
} else {
future.complete(value);
}
} else {
throw new IllegalStateException("The async response has probably been wrote back by another thread, or the asyncContext has been closed.");
}
}