Dubbo源码分析之异步回调

知识共享许可协议 版权声明:署名,允许他人基于本文进行创作,且必须基于与原先许可协议相同的许可协议分发本文 (Creative Commons

异步回调需要设置方法返回值为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);
    }
});

猜你喜欢

转载自blog.csdn.net/ph3636/article/details/91873650