异步回调需要设置方法返回值为CompletableFuture或者他的子类
消费端
判断返回值,设置参数异步加回调
class InvokerInvocationHandler implements InvocationHandler
private RpcInvocation createInvocation(Method method, Object[] args) {
RpcInvocation invocation = new RpcInvocation(method, args);
if (RpcUtils.hasFutureReturnType(method)) {
invocation.setAttachment(Constants.FUTURE_RETURNTYPE_KEY, "true");
invocation.setAttachment(Constants.ASYNC_KEY, "true");
}
return invocation;
}
如果是异步的话就添加调用id参数
abstract class AbstractClusterInvoker<T> implements Invoker<T>
public static Long getInvocationId(Invocation inv) {
String id = inv.getAttachment(Constants.ID_KEY);
return id == null ? null : new Long(id);
}
public static void attachInvocationIdIfAsync(URL url, Invocation inv) {
if (isAttachInvocationId(url, inv) && getInvocationId(inv) == null && inv instanceof RpcInvocation) {
((RpcInvocation) inv).setAttachment(Constants.ID_KEY, String.valueOf(INVOKE_ID.getAndIncrement()));
}
}
private static boolean isAttachInvocationId(URL url, Invocation invocation) {
String value = url.getMethodParameter(invocation.getMethodName(), Constants.AUTO_ATTACH_INVOCATIONID_KEY);
if (value == null) {
// add invocationid in async operation by default
return isAsync(url, invocation);
} else if (Boolean.TRUE.toString().equalsIgnoreCase(value)) {
return true;
} else {
return false;
}
}
判断异步凡是开始调用
class DubboInvoker<T> extends AbstractInvoker<T>
boolean isAsync = RpcUtils.isAsync(getUrl(), invocation);
boolean isAsyncFuture = RpcUtils.isReturnTypeFuture(inv);
if (isAsync) {
ResponseFuture future = currentClient.request(inv, timeout);
// For compatibility
FutureAdapter<Object> futureAdapter = new FutureAdapter<>(future);
RpcContext.getContext().setFuture(futureAdapter);
Result result;
if (isAsyncFuture) {
// register resultCallback, sometimes we need the async result being processed by the filter chain.
result = new AsyncRpcResult(futureAdapter, futureAdapter.getResultFuture(), false);
} else {
result = new SimpleAsyncRpcResult(futureAdapter, futureAdapter.getResultFuture(), false);
}
return result;
}
把返回值组装成FutureAdapter并保存在线程中,普通得单纯异步不需要设置方法返回值,只需要设置方法参数async = "true",获取最终结果就是从当前线程保存的FutureAdapter中得到。
public FutureAdapter(ResponseFuture future) {
this.future = future;
this.resultFuture = new CompletableFuture<>();
future.setCallback(new ResponseCallback() {
@Override
public void done(Object response) {
Result result = (Result) response;
FutureAdapter.this.resultFuture.complete(result);
V value = null;
try {
value = (V) result.recreate();
} catch (Throwable t) {
FutureAdapter.this.completeExceptionally(t);
}
FutureAdapter.this.complete(value);
}
@Override
public void caught(Throwable exception) {
FutureAdapter.this.completeExceptionally(exception);
}
});
}
组装返回值结果返回给调用代码块
public AsyncRpcResult(CompletableFuture<Object> future, final CompletableFuture<Result> rFuture, boolean registerCallback) {
if (rFuture == null) {
throw new IllegalArgumentException();
}
resultFuture = rFuture;
if (registerCallback) {
/**
* We do not know whether future already completed or not, it's a future exposed or even created by end user.
* 1. future complete before whenComplete. whenComplete fn (resultFuture.complete) will be executed in thread subscribing, in our case, it's Dubbo thread.
* 2. future complete after whenComplete. whenComplete fn (resultFuture.complete) will be executed in thread calling complete, normally its User thread.
*/
future.whenComplete((v, t) -> {
RpcResult rpcResult;
if (t != null) {
if (t instanceof CompletionException) {
rpcResult = new RpcResult(t.getCause());
} else {
rpcResult = new RpcResult(t);
}
} else {
rpcResult = new RpcResult(v);
}
// instead of resultFuture we must use rFuture here, resultFuture may being changed before complete when building filter chain, but rFuture was guaranteed never changed by closure.
rFuture.complete(rpcResult);
});
}
this.valueFuture = future;
// employ copy of context avoid the other call may modify the context content
this.storedContext = RpcContext.getContext().copyOf();
this.storedServerContext = RpcContext.getServerContext().copyOf();
}
消息发送之前会创建一个DefaultFuture返回,有定时程序一直在检查是否超时
public static DefaultFuture newFuture(Channel channel, Request request, int timeout) {
final DefaultFuture future = new DefaultFuture(channel, request, timeout);
// timeout check
timeoutCheck(future);
return future;
}
private DefaultFuture(Channel channel, Request request, int timeout) {
this.channel = channel;
this.request = request;
this.id = request.getId();
this.timeout = timeout > 0 ? timeout : channel.getUrl().getPositiveParameter(Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT);
// put into waiting map.
FUTURES.put(id, this);
CHANNELS.put(id, channel);
}
超时等待
public Object get(int timeout) throws RemotingException {
if (timeout <= 0) {
timeout = Constants.DEFAULT_TIMEOUT;
}
if (!isDone()) {
long start = System.currentTimeMillis();
lock.lock();
try {
while (!isDone()) {
done.await(timeout, TimeUnit.MILLISECONDS);
if (isDone() || System.currentTimeMillis() - start > timeout) {
break;
}
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
lock.unlock();
}
if (!isDone()) {
throw new TimeoutException(sent > 0, channel, getTimeoutMessage(false));
}
}
return returnFromResponse();
}
当有响应结果时
DefaultFuture.received(channel, response);
public static void received(Channel channel, Response response) {
try {
DefaultFuture future = FUTURES.remove(response.getId());
if (future != null) {
future.doReceived(response);
} else {
logger.warn("The timeout response finally returned at "
+ (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()))
+ ", response " + response
+ (channel == null ? "" : ", channel: " + channel.getLocalAddress()
+ " -> " + channel.getRemoteAddress()));
}
} finally {
CHANNELS.remove(response.getId());
}
}
private void doReceived(Response res) {
lock.lock();
try {
response = res;
done.signalAll();
} finally {
lock.unlock();
}
if (callback != null) {
invokeCallback(callback);
}
}
唤醒等待返回结果。
private Object returnFromResponse() throws RemotingException {
Response res = response;
if (res == null) {
throw new IllegalStateException("response cannot be null");
}
if (res.getStatus() == Response.OK) {
return res.getResult();
}
if (res.getStatus() == Response.CLIENT_TIMEOUT || res.getStatus() == Response.SERVER_TIMEOUT) {
throw new TimeoutException(res.getStatus() == Response.SERVER_TIMEOUT, channel, res.getErrorMessage());
}
throw new RemotingException(channel, res.getErrorMessage());
}
执行DefaultFuture设置的回调函数
private void invokeCallback(ResponseCallback c) {
ResponseCallback callbackCopy = c;
if (callbackCopy == null) {
throw new NullPointerException("callback cannot be null.");
}
Response res = response;
if (res == null) {
throw new IllegalStateException("response cannot be null. url:" + channel.getUrl());
}
if (res.getStatus() == Response.OK) {
try {
callbackCopy.done(res.getResult());
} catch (Exception e) {
logger.error("callback invoke error .result:" + res.getResult() + ",url:" + channel.getUrl(), e);
}
} else if (res.getStatus() == Response.CLIENT_TIMEOUT || res.getStatus() == Response.SERVER_TIMEOUT) {
try {
TimeoutException te = new TimeoutException(res.getStatus() == Response.SERVER_TIMEOUT, channel, res.getErrorMessage());
callbackCopy.caught(te);
} catch (Exception e) {
logger.error("callback invoke error ,url:" + channel.getUrl(), e);
}
} else {
try {
RuntimeException re = new RuntimeException(res.getErrorMessage());
callbackCopy.caught(re);
} catch (Exception e) {
logger.error("callback invoke error ,url:" + channel.getUrl(), e);
}
}
}
如果结果正确的话就执行done函数resultFuture设置完成结果,然后拆解出具体的返回结果设置到FutureAdapter上也就是valueFuture,因为registerCallback未false所以不用重新设置resultFuture该值,最后消费端得到具体值回调。
invoker.invoke(createInvocation(method, args)).recreate();
public Object recreate() throws Throwable {
return valueFuture;
}
提供端
开始处理请求
class HeaderExchangeHandler implements ChannelHandlerDelegate
// handle data.
CompletableFuture<Object> future = handler.reply(channel, msg);
判断返回状态直接返回结果,registerCallback为true,resultFuture结果为空对象,当提供者处理完请求并返回结果时,这里的valueFuture = future会执行完成方法future.whenComplete,把结果进行包装后设置到resultFuture = rFuture,
abstract class AbstractProxyInvoker<T> implements Invoker<T>
Object obj = doInvoke(proxy, invocation.getMethodName(), invocation.getParameterTypes(), invocation.getArguments());
if (RpcUtils.isReturnTypeFuture(invocation))
return new AsyncRpcResult((CompletableFuture<Object>) obj);
}
public AsyncRpcResult(CompletableFuture<Object> future) {
this(future, true);
}
public AsyncRpcResult(CompletableFuture<Object> future, boolean registerCallback) {
this(future, new CompletableFuture<>(), registerCallback);
}
判断返回结果类型并包装成回调类型,这里会获取resultFuture返回。
class DubboProtocol extends AbstractProtocol
if (result instanceof AsyncRpcResult) {
return ((AsyncRpcResult) result).getResultFuture().thenApply(r -> (Object) r);
} else {
return CompletableFuture.completedFuture(result);
}
判断返回状态,方法执行完的话就直接返回,否则的话设置回调函数,当处理完请求后再返回给消费端,前面返回的resultFuture会触发whenComplete方法。
class HeaderExchangeHandler implements ChannelHandlerDelegate
if (future.isDone()) {
res.setStatus(Response.OK);
res.setResult(future.get());
channel.send(res);
return;
}
future.whenComplete((result, t) -> {
try {
if (t == null) {
res.setStatus(Response.OK);
res.setResult(result);
} else {
res.setStatus(Response.SERVICE_ERROR);
res.setErrorMessage(StringUtils.toString(t));
}
channel.send(res);
} catch (RemotingException e) {
logger.warn("Send result to consumer failed, channel is " + channel + ", msg is " + e);
} finally {
// HeaderExchangeChannel.removeChannelIfDisconnected(channel);
}
});