Dubbo中服務消費者和服務提供者之間的請求和響應過程

服務提供者初始化完成之后反镇,對外暴露Exporter。服務消費者初始化完成之后送火,得到的是Proxy代理拳话,方法調用的時候就是調用代理。

服務消費者經過初始化之后种吸,得到的是一個動態(tài)代理類弃衍,InvokerInvocationHandler,包含MockClusterInvoker坚俗,MockClusterInvoker包含一個RegistryDirectory和FailoverClusterInvoker镜盯。

Java動態(tài)代理,每一個動態(tài)代理類都必須要實現InvocationHandler這個接口坦冠,并且每一個代理類的實例都關聯到了一個handler形耗,當我們通過代理對象調用一個方法的時候,這個方法就會被轉發(fā)為由實現了InvocationHandler這個接口的類的invoke方法來進行調用辙浑。

服務消費者發(fā)起調用請求

InvokerInvocationHandler實現了InvocationHandler接口激涤,當我們調用helloService.sayHello();的時候,實際上會調用invoke()方法:

//proxy是代理的真實對象
//method調用真實對象的方法
//args調用真實對象的方法的參數
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    //方法名sayHello
    String methodName = method.getName();
    //參數類型
    Class<?>[] parameterTypes = method.getParameterTypes();
    if (method.getDeclaringClass() == Object.class) {
        return method.invoke(invoker, args);
    }
    if ("toString".equals(methodName) && parameterTypes.length == 0) {
        return invoker.toString();
    }
    if ("hashCode".equals(methodName) && parameterTypes.length == 0) {
        return invoker.hashCode();
    }
    if ("equals".equals(methodName) && parameterTypes.length == 1) {
        return invoker.equals(args[0]);
    }
    //invoker是MockClusterInvoker
    //首先new RpcInvocation
    //然后invoker.invoke
    //最后recreate
    //返回結果
    return invoker.invoke(new RpcInvocation(method, args)).recreate();
}

先看下new RpcInvocation判呕,Invocation是會話域倦踢,它持有調用過程中的變量,比如方法名侠草,參數類型等辱挥。

接著是invoker.invoke(),這里invoker是MockClusterInvoker边涕,進入MockClusterInvoker.invoker():

public Result invoke(Invocation invocation) throws RpcException {
    Result result = null;
    //獲取mock屬性的值晤碘,我們沒有配置褂微,默認false
    String value = directory.getUrl().getMethodParameter(invocation.getMethodName(), Constants.MOCK_KEY, Boolean.FALSE.toString()).trim(); 
    if (value.length() == 0 || value.equalsIgnoreCase("false")){
        //這里invoker是FailoverClusterInvoker
        result = this.invoker.invoke(invocation);
    } else if (value.startsWith("force")) {
        //force:direct mock
        result = doMockInvoke(invocation, null);
    } else {
        //fail-mock
        try {
            result = this.invoker.invoke(invocation);
        }catch (RpcException e) {
            if (e.isBiz()) {
                throw e;
            } else {
                result = doMockInvoke(invocation, e);
            }
        }
    }
    return result;
}

result = this.invoker.invoke(invocation);這里invoker是FailoverClusterInvoker,會首先進入AbstractClusterInvoker的invoke方法:

public Result invoke(final Invocation invocation) throws RpcException {
    //檢查是否被銷毀
    checkWheatherDestoried();
    LoadBalance loadbalance;
    //根據invocation中的參數來獲取所有的invoker列表
    List<Invoker<T>> invokers = list(invocation);
    if (invokers != null && invokers.size() > 0) {
        //我們沒有配置負載均衡的參數园爷,默認使用random
        //這里得到的是RandomLoadBalance
        loadbalance = ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(invokers.get(0).getUrl()
                .getMethodParameter(invocation.getMethodName(),Constants.LOADBALANCE_KEY, Constants.DEFAULT_LOADBALANCE));
    } else {
        loadbalance = ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(Constants.DEFAULT_LOADBALANCE);
    }
    //如果是異步操作默認添加invocation id
    RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);
    //這里是子類實現宠蚂,FailoverClusterInvoker中,執(zhí)行調用
    return doInvoke(invocation, invokers, loadbalance);
}

FailoverClusterInvoker.doInvoke():

public Result doInvoke(Invocation invocation, final List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
    List<Invoker<T>> copyinvokers = invokers;
    //檢查invokers是否為空
    checkInvokers(copyinvokers, invocation);
    //重試次數
    int len = getUrl().getMethodParameter(invocation.getMethodName(), Constants.RETRIES_KEY, Constants.DEFAULT_RETRIES) + 1;
    if (len <= 0) {
        len = 1;
    }
    // retry loop.
    RpcException le = null; // last exception.
    //已經調用過的invoker
    List<Invoker<T>> invoked = new ArrayList<Invoker<T>>(copyinvokers.size()); // invoked invokers.
    Set<String> providers = new HashSet<String>(len);
    for (int i = 0; i < len; i++) {
        //重試時童社,進行重新選擇求厕,避免重試時invoker列表已發(fā)生變化.
        //注意:如果列表發(fā)生了變化,那么invoked判斷會失效扰楼,因為invoker示例已經改變
        if (i > 0) {
            checkWheatherDestoried();
            copyinvokers = list(invocation);
            //重新檢查一下
            checkInvokers(copyinvokers, invocation);
        }
        //使用負載均衡選擇invoker.(負載均衡咱先不做解釋)
        Invoker<T> invoker = select(loadbalance, invocation, copyinvokers, invoked);
        invoked.add(invoker);
        //添加到以調用過的列表中
        RpcContext.getContext().setInvokers((List)invoked);
        try {
            //開始調用呀癣,返回結果
            Result result = invoker.invoke(invocation);
            return result;
        } catch (RpcException e) {。弦赖。项栏。 } finally {
            providers.add(invoker.getUrl().getAddress());
        }
    }
    throw new RpcException(。蹬竖。忘嫉。);
}

Result result = invoker.invoke(invocation);調用并返回結果,會首先進入InvokerWrapper案腺,然后進入ListenerInvokerWrapper的invoke方法,接著進入AbstractInvoker的invoke:

public Result invoke(Invocation inv) throws RpcException {
    if(destroyed) {
        throw new RpcException(康吵。劈榨。。);
    }
    //轉成RpcInvocation
    RpcInvocation invocation = (RpcInvocation) inv;
    invocation.setInvoker(this);
    if (attachment != null && attachment.size() > 0) {
        invocation.addAttachmentsIfAbsent(attachment);
    }
    Map<String, String> context = RpcContext.getContext().getAttachments();
    if (context != null) {
        invocation.addAttachmentsIfAbsent(context);
    }
    if (getUrl().getMethodParameter(invocation.getMethodName(), Constants.ASYNC_KEY, false)){
        invocation.setAttachment(Constants.ASYNC_KEY, Boolean.TRUE.toString());
    }
    //異步的話晦嵌,需要添加id
    RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);
    try {
        //這里是DubboInvoker
        return doInvoke(invocation);
    } catch (InvocationTargetException e) { } 
}

DubboInvoker.doInvoke():

protected Result doInvoke(final Invocation invocation) throws Throwable {
    RpcInvocation inv = (RpcInvocation) invocation;
    final String methodName = RpcUtils.getMethodName(invocation);
    inv.setAttachment(Constants.PATH_KEY, getUrl().getPath());
    inv.setAttachment(Constants.VERSION_KEY, version);

    ExchangeClient currentClient;
    //在初始化的時候同辣,引用服務的過程中會保存一個連接到服務端的Client
    if (clients.length == 1) {
        currentClient = clients[0];
    } else {
        currentClient = clients[index.getAndIncrement() % clients.length];
    }
    try {
        //異步標志
        boolean isAsync = RpcUtils.isAsync(getUrl(), invocation);
        //單向標志
        boolean isOneway = RpcUtils.isOneway(getUrl(), invocation);
        int timeout = getUrl().getMethodParameter(methodName, Constants.TIMEOUT_KEY,Constants.DEFAULT_TIMEOUT);
        //單向的,反送完不管結果
        if (isOneway) {
            boolean isSent = getUrl().getMethodParameter(methodName, Constants.SENT_KEY, false);
            currentClient.send(inv, isSent);
            RpcContext.getContext().setFuture(null);
            return new RpcResult();
        } else if (isAsync) {//異步的惭载,發(fā)送完需要得到Future
            ResponseFuture future = currentClient.request(inv, timeout) ;
            RpcContext.getContext().setFuture(new FutureAdapter<Object>(future));
            return new RpcResult();
        } else {//同步調用旱函,我們這里使用的這種方式
            RpcContext.getContext().setFuture(null);
            //HeaderExchangeClient
            return (Result) currentClient.request(inv, timeout).get();
        }
    } catch (TimeoutException e) {。描滔。棒妨。}
}

我們這里使用的是同步調用,看(Result) currentClient.request(inv, timeout).get();方法含长,這里的client是ReferenceCountExchangeClient券腔,直接調用HeaderExchangeClient的request方法:

public ResponseFuture request(Object request, int timeout) throws RemotingException {
    //這里的Channel是HeaderExchangeChannel
    return channel.request(request, timeout);
}

進入HeaderExchangeChannel的request方法:

public ResponseFuture request(Object request, int timeout) throws RemotingException {
    if (closed) {
        throw new RemotingException(。拘泞。纷纫。);
    }
    //創(chuàng)建一個請求頭
    Request req = new Request();
    req.setVersion("2.0.0");
    req.setTwoWay(true);
    //這里request參數里面保存著
    //methodName = "sayHello"
    //parameterTypes = {Class[0]@2814} 
    //arguments = {Object[0]@2768} 
    //attachments = {HashMap@2822}  size = 4
    //invoker = {DubboInvoker@2658}
    req.setData(request);
    DefaultFuture future = new DefaultFuture(channel, req, timeout);
    try{
        //這里的channel是NettyClient
        //發(fā)送請求
        channel.send(req);
    }catch (RemotingException e) {
        future.cancel();
        throw e;
    }
    return future;
}

channel.send(req),首先會調用AbstractPeer的send方法:

//子類處理陪腌,接著是AbstractClient執(zhí)行發(fā)送
public void send(Object message) throws RemotingException {
    send(message, url.getParameter(Constants.SENT_KEY, false));
}

AbstractClient執(zhí)行發(fā)送:

public void send(Object message, boolean sent) throws RemotingException {
    //重連
    if (send_reconnect && !isConnected()){
        connect();
    }
    //先獲取Channel辱魁,是在NettyClient中實現的
    Channel channel = getChannel();
    //TODO getChannel返回的狀態(tài)是否包含null需要改進
    if (channel == null || ! channel.isConnected()) {
      throw new RemotingException(this, "message can not send, because channel is closed . url:" + getUrl());
    }
    channel是NettyChannel
    channel.send(message, sent);
}

channel.send(message, sent);首先經過AbstractChannel的send方法處理烟瞧,只是判斷是否關閉了,然后是NettyChannel的send來繼續(xù)處理染簇,這里就把消息發(fā)送到服務端了:

public void send(Object message, boolean sent) throws RemotingException {
    super.send(message, sent);

    boolean success = true;
    int timeout = 0;
    try {
        //交給netty處理
        ChannelFuture future = channel.write(message);
        if (sent) {
            timeout = getUrl().getPositiveParameter(Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT);
            success = future.await(timeout);
        }
        Throwable cause = future.getCause();
        if (cause != null) {
            throw cause;
        }
    } catch (Throwable e) {
        throw new RemotingException(this, "Failed to send message " + message + " to " + getRemoteAddress() + ", cause: " + e.getMessage(), e);
    }

    if(! success) {
        throw new RemotingException(this, "Failed to send message " + message + " to " + getRemoteAddress()
                + "in timeout(" + timeout + "ms) limit");
    }
}

服務提供者處理并響應請求

服務端已經打開端口并監(jiān)聽請求的到來参滴,當服務消費者發(fā)送調用請求的時候,經過Netty的處理后會到dubbo中的codec相關方法中先進行解碼剖笙,入口是NettyCodecAdapter.messageReceived()卵洗,關于這個方法的代碼在dubbo編解碼的那篇文章中已經分析過,不再重復弥咪。經過解碼之后过蹂,會進入到NettyHandler.messageReceived()方法:

public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
    //獲取channel
    NettyChannel channel = NettyChannel.getOrAddChannel(ctx.getChannel(), url, handler);
    try {
        //這里handler是NettyServer
        handler.received(channel, e.getMessage());
    } finally {
        NettyChannel.removeChannelIfDisconnected(ctx.getChannel());
    }
}

接著會進入AbstractPeer的received方法:

public void received(Channel ch, Object msg) throws RemotingException {
    if (closed) {
        return;
    }
    //這里是MultiMessageHandler
    handler.received(ch, msg);
}

進入MultiMessageHandler的received方法:

public void received(Channel channel, Object message) throws RemotingException {
    //是多消息的話,使用多消息處理器處理
    if (message instanceof MultiMessage) {
        MultiMessage list = (MultiMessage)message;
        for(Object obj : list) {
            handler.received(channel, obj);
        }
    } else {
        //這里是HeartbeatHandler
        handler.received(channel, message);
    }
}

進入HeartbeatHandler的received方法:

public void received(Channel channel, Object message) throws RemotingException {
    setReadTimestamp(channel);
    //心跳請求處理
    if (isHeartbeatRequest(message)) {
        Request req = (Request) message;
        if (req.isTwoWay()) {
            Response res = new Response(req.getId(), req.getVersion());
            res.setEvent(Response.HEARTBEAT_EVENT);
            channel.send(res);
        }
        return;
    }
    //心跳回應消息處理
    if (isHeartbeatResponse(message)) {
        return;
    }
    //這里是AllChannelHandler
    handler.received(channel, message);
}

繼續(xù)進入AllChannelHandler的received方法:

public void received(Channel channel, Object message) throws RemotingException {
    //獲取線程池執(zhí)行
    ExecutorService cexecutor = getExecutorService();
    try {
        //handler是DecodeHandler
        cexecutor.execute(new ChannelEventRunnable(channel, handler, ChannelState.RECEIVED, message));
    } catch (Throwable t) { }
}

這里會去啟動新線程執(zhí)行ChannelEventRunnable的run方法聚至,接著去調用DecodeHandler的received方法:

public void received(Channel channel, Object message) throws RemotingException {
    //不清楚啥意思
    if (message instanceof Decodeable) {
        decode(message);
    }
    //解碼請求類型
    if (message instanceof Request) {
        decode(((Request)message).getData());
    }
    //解碼響應類型
    if (message instanceof Response) {
        decode( ((Response)message).getResult());
    }
    //解碼之后到HeaderExchangeHandler中處理
    handler.received(channel, message);
}

解碼之后到HeaderExchangeHandler的received方法:

public void received(Channel channel, Object message) throws RemotingException {
    channel.setAttribute(KEY_READ_TIMESTAMP, System.currentTimeMillis());
    ExchangeChannel exchangeChannel = HeaderExchangeChannel.getOrAddChannel(channel);
    try {
        //request類型的消息
        if (message instanceof Request) {
            Request request = (Request) message;
            if (request.isEvent()) {//判斷心跳還是正常請求
                //  處理心跳
                handlerEvent(channel, request);
            } else {//正常的請求
                //需要返回
                if (request.isTwoWay()) {
                    //處理請求酷勺,并構造響應信息
                    Response response = handleRequest(exchangeChannel, request);
                    //NettyChannel,發(fā)送響應信息
                    channel.send(response);
                } else {//不需要返回的處理
                    handler.received(exchangeChannel, request.getData());
                }
            }
        } else if (message instanceof Response) {//response類型的消息
            handleResponse(channel, (Response) message);
        } else if (message instanceof String) {
            if (isClientSide(channel)) {
                Exception e = new Exception("Dubbo client can not supported string message: " + message + " in channel: " + channel + ", url: " + channel.getUrl());
            } else {//telnet類型
                String echo = handler.telnet(channel, (String) message);
                if (echo != null && echo.length() > 0) {
                    channel.send(echo);
                }
            }
        } else {
            handler.received(exchangeChannel, message);
        }
    } finally {
        HeaderExchangeChannel.removeChannelIfDisconnected(channel);
    }
}

先看下處理請求扳躬,并構造響應信息:

Response handleRequest(ExchangeChannel channel, Request req) throws RemotingException {
    Response res = new Response(req.getId(), req.getVersion());
    if (req.isBroken()) {
        Object data = req.getData();

        String msg;
        if (data == null) msg = null;
        else if (data instanceof Throwable) msg = StringUtils.toString((Throwable) data);
        else msg = data.toString();
        res.setErrorMessage("Fail to decode request due to: " + msg);
        res.setStatus(Response.BAD_REQUEST);

        return res;
    }
    // find handler by message class.
    Object msg = req.getData();
    try {
        //處理請求數據脆诉,handler是DubboProtocol中的new的一個ExchangeHandlerAdapter
        Object result = handler.reply(channel, msg);
        res.setStatus(Response.OK);
        res.setResult(result);
    } catch (Throwable e) { }
    return res;
}

進入DubboProtocol中的ExchangeHandlerAdapter的replay方法:

public Object reply(ExchangeChannel channel, Object message) throws RemotingException {
        if (message instanceof Invocation) {
            //Invocation中保存著方法名等
            Invocation inv = (Invocation) message;
            //獲取Invoker
            Invoker<?> invoker = getInvoker(channel, inv);
            //如果是callback 需要處理高版本調用低版本的問題
            if (Boolean.TRUE.toString().equals(inv.getAttachments().get(IS_CALLBACK_SERVICE_INVOKE))){
                String methodsStr = invoker.getUrl().getParameters().get("methods");
                boolean hasMethod = false;
                if (methodsStr == null || methodsStr.indexOf(",") == -1){
                    hasMethod = inv.getMethodName().equals(methodsStr);
                } else {
                    String[] methods = methodsStr.split(",");
                    for (String method : methods){
                        if (inv.getMethodName().equals(method)){
                            hasMethod = true;
                            break;
                        }
                    }
                }
                if (!hasMethod){
                    return null;
                }
            }
            RpcContext.getContext().setRemoteAddress(channel.getRemoteAddress());
            //執(zhí)行調用,然后返回結果
            return invoker.invoke(inv);
        }
        throw new RemotingException(贷币。击胜。。);
    }

先看下getInvoker獲取Invoker:

Invoker<?> getInvoker(Channel channel, Invocation inv) throws RemotingException{
    boolean isCallBackServiceInvoke = false;
    boolean isStubServiceInvoke = false;
    int port = channel.getLocalAddress().getPort();
    String path = inv.getAttachments().get(Constants.PATH_KEY);
    //如果是客戶端的回調服務.
    isStubServiceInvoke = Boolean.TRUE.toString().equals(inv.getAttachments().get(Constants.STUB_EVENT_KEY));
    if (isStubServiceInvoke){
        port = channel.getRemoteAddress().getPort();
    }
    //callback
    isCallBackServiceInvoke = isClientSide(channel) && !isStubServiceInvoke;
    if(isCallBackServiceInvoke){
        path = inv.getAttachments().get(Constants.PATH_KEY)+"."+inv.getAttachments().get(Constants.CALLBACK_SERVICE_KEY);
        inv.getAttachments().put(IS_CALLBACK_SERVICE_INVOKE, Boolean.TRUE.toString());
    }
    String serviceKey = serviceKey(port, path, inv.getAttachments().get(Constants.VERSION_KEY), inv.getAttachments().get(Constants.GROUP_KEY));
    //從之前緩存的exporterMap中查找Exporter
    //key:dubbo.common.hello.service.HelloService:20880
    DubboExporter<?> exporter = (DubboExporter<?>) exporterMap.get(serviceKey);

    if (exporter == null)
        throw new RemotingException(役纹。偶摔。。);
    //得到Invoker促脉,返回
    return exporter.getInvoker();
}

再看執(zhí)行調用invoker.invoke(inv);辰斋,會先進入InvokerWrapper:

public Result invoke(Invocation invocation) throws RpcException {
    return invoker.invoke(invocation);
}

接著進入AbstractProxyInvoker:

public Result invoke(Invocation invocation) throws RpcException {
    try {
        //先doInvoke
        //然后封裝成結果返回
        return new RpcResult(doInvoke(proxy, invocation.getMethodName(), invocation.getParameterTypes(), invocation.getArguments()));
    } catch (InvocationTargetException e) {。瘸味。宫仗。}
}

這里的doInvoke是在JavassistProxyFactory中的AbstractProxyInvoker實例:

public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
    // TODO Wrapper類不能正確處理帶$的類名
    final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass().getName().indexOf('$') < 0 ? proxy.getClass() : type);
    return new AbstractProxyInvoker<T>(proxy, type, url) {
        @Override
        protected Object doInvoke(T proxy, String methodName, 
                                  Class<?>[] parameterTypes, 
                                  Object[] arguments) throws Throwable {
                                  //這里就調用了具體的方法
            return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments);
        }
    };
}

消息處理完后返回到HeaderExchangeHandler的received方法:

public void received(Channel channel, Object message) throws RemotingException {
    channel.setAttribute(KEY_READ_TIMESTAMP, System.currentTimeMillis());
    ExchangeChannel exchangeChannel = HeaderExchangeChannel.getOrAddChannel(channel);
    try {
        //request類型的消息
        if (message instanceof Request) {
            Request request = (Request) message;
            if (request.isEvent()) {//判斷心跳還是正常請求
                //  處理心跳
                handlerEvent(channel, request);
            } else {//正常的請求
                //需要返回
                if (request.isTwoWay()) {
                    //處理請求,并構造響應信息旁仿,這在上面已經解析過了
                    Response response = handleRequest(exchangeChannel, request);
                    //NettyChannel藕夫,發(fā)送響應信息
                    channel.send(response);
                } else {//不需要返回的處理
                    handler.received(exchangeChannel, request.getData());
                }
            }
        } else if (message instanceof Response) {//response類型的消息
            handleResponse(channel, (Response) message);
        } else if (message instanceof String) {
            if (isClientSide(channel)) {
                Exception e = new Exception("Dubbo client can not supported string message: " + message + " in channel: " + channel + ", url: " + channel.getUrl());
            } else {//telnet類型
                String echo = handler.telnet(channel, (String) message);
                if (echo != null && echo.length() > 0) {
                    channel.send(echo);
                }
            }
        } else {
            handler.received(exchangeChannel, message);
        }
    } finally {
        HeaderExchangeChannel.removeChannelIfDisconnected(channel);
    }
}

解析完請求,構造完響應消息丁逝,就開始發(fā)送響應了,channel.send(response);汁胆,先經過AbstractPeer:

public void send(Object message) throws RemotingException {
    //NettyChannel
    send(message, url.getParameter(Constants.SENT_KEY, false));
}

進入NettyChannel中,進行響應消息的發(fā)送:

public void send(Object message, boolean sent) throws RemotingException {
    //AbstractChannel的處理
    super.send(message, sent);

    boolean success = true;
    int timeout = 0;
    try {
        ChannelFuture future = channel.write(message);
        if (sent) {
            timeout = getUrl().getPositiveParameter(Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT);
            success = future.await(timeout);
        }
        Throwable cause = future.getCause();
        if (cause != null) {
            throw cause;
        }
    } catch (Throwable e) {
        throw new RemotingException(this, "Failed to send message " + message + " to " + getRemoteAddress() + ", cause: " + e.getMessage(), e);
    }

    if(! success) {
        throw new RemotingException(this, "Failed to send message " + message + " to " + getRemoteAddress()
                + "in timeout(" + timeout + "ms) limit");
    }
}

消費者接受到服務端返回的響應后的處理

服務提供者端接收到消費者端的請求并處理之后霜幼,返回給消費者端嫩码,消費者這邊接受響應的入口跟提供者差不多,也是NettyCodecAdapter.messageReceived()罪既,經過解碼铸题,到NettyHandler.messageReceived()處理:

public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
    NettyChannel channel = NettyChannel.getOrAddChannel(ctx.getChannel(), url, handler);
    try {
        //NettyClient
        handler.received(channel, e.getMessage());
    } finally {
        NettyChannel.removeChannelIfDisconnected(ctx.getChannel());
    }
}

先經過AbstractPeer的received方法:

public void received(Channel ch, Object msg) throws RemotingException {
    if (closed) {
        return;
    }
    //MultiMessageHandler
    handler.received(ch, msg);
}

進入MultiMessageHandler:

public void received(Channel channel, Object message) throws RemotingException {
    if (message instanceof MultiMessage) {
        MultiMessage list = (MultiMessage)message;
        for(Object obj : list) {
            handler.received(channel, obj);
        }
    } else {
        //HeartbeatHandler
        handler.received(channel, message);
    }
}

進入HeartbeatHandler铡恕,根據不同類型進行處理:

public void received(Channel channel, Object message) throws RemotingException {
    setReadTimestamp(channel);
    if (isHeartbeatRequest(message)) {
        Request req = (Request) message;
        if (req.isTwoWay()) {
            Response res = new Response(req.getId(), req.getVersion());
            res.setEvent(Response.HEARTBEAT_EVENT);
            channel.send(res);
            if (logger.isInfoEnabled()) {
                int heartbeat = channel.getUrl().getParameter(Constants.HEARTBEAT_KEY, 0);
                if(logger.isDebugEnabled()) {
                    logger.debug("Received heartbeat from remote channel " + channel.getRemoteAddress()
                                    + ", cause: The channel has no data-transmission exceeds a heartbeat period"
                                    + (heartbeat > 0 ? ": " + heartbeat + "ms" : ""));
                }
            }
        }
        return;
    }
    if (isHeartbeatResponse(message)) {
        if (logger.isDebugEnabled()) {
            logger.debug(
                new StringBuilder(32)
                    .append("Receive heartbeat response in thread ")
                    .append(Thread.currentThread().getName())
                    .toString());
        }
        return;
    }
    //AllChannelHandler
    handler.received(channel, message);
}

進入AllChannelHandler:

public void received(Channel channel, Object message) throws RemotingException {
    ExecutorService cexecutor = getExecutorService();
    try {
        cexecutor.execute(new ChannelEventRunnable(channel, handler, ChannelState.RECEIVED, message));
    } catch (Throwable t) {
        throw new ExecutionException(message, channel, getClass() + " error when process received event .", t);
    }
}

然后在新線程,ChannelEventRunnable的run方法中進入DecodeHandler:

public void received(Channel channel, Object message) throws RemotingException {
    if (message instanceof Decodeable) {
        decode(message);
    }

    if (message instanceof Request) {
        decode(((Request)message).getData());
    }
    //這里進行response類型的處理
    if (message instanceof Response) {
        decode( ((Response)message).getResult());
    }

    handler.received(channel, message);
}

進入處理response的decode方法丢间,進行解碼response:

private void decode(Object message) {
    if (message != null && message instanceof Decodeable) {
        try {
            ((Decodeable)message).decode();
        } catch (Throwable e) {探熔。。烘挫。} // ~ end of catch
    } // ~ end of if
} 

接著會進入HeaderExchangerHandler.received () 方法:

public void received(Channel channel, Object message) throws RemotingException {
    channel.setAttribute(KEY_READ_TIMESTAMP, System.currentTimeMillis());
    ExchangeChannel exchangeChannel = HeaderExchangeChannel.getOrAddChannel(channel);
    try {
        if (message instanceof Request) {
            Request request = (Request) message;
            if (request.isEvent()) {
                handlerEvent(channel, request);
            } else {
                if (request.isTwoWay()) {
                    Response response = handleRequest(exchangeChannel, request);
                    channel.send(response);
                } else {
                    handler.received(exchangeChannel, request.getData());
                }
            }
        } else if (message instanceof Response) {
            //這里處理response消息
            handleResponse(channel, (Response) message);
        } else if (message instanceof String) {
            if (isClientSide(channel)) {  Exception  } else {
                String echo = handler.telnet(channel, (String) message);
                if (echo != null && echo.length() > 0) {
                    channel.send(echo);
                }
            }
        } else {
            handler.received(exchangeChannel, message);
        }
    } finally {
        HeaderExchangeChannel.removeChannelIfDisconnected(channel);
    }
}

handleResponse方法:

static void handleResponse(Channel channel, Response response) throws RemotingException {
    if (response != null && !response.isHeartbeat()) {
        DefaultFuture.received(channel, response);
    }
}

這一步設置response到消費者請求的Future中诀艰,以供消費者通過DefaultFuture.get()取得提供者的響應,此為同步轉異步重要一步饮六,且請求超時也由DefaultFuture控制其垄。

然后就是return (Result) currentClient.request(inv, timeout).get();在DubboInvoker中,這里繼續(xù)執(zhí)行卤橄,然后執(zhí)行Filter绿满,最后返回到InvokerInvocationHandler.invoker()方法中,方法得到調用結果窟扑,結束喇颁!

注意:

消費者端的DubboInvoker發(fā)起請求后,后續(xù)的邏輯是異步的或是指定超時時間內阻塞的嚎货,直到得到響應結果后橘霎,繼續(xù)執(zhí)行DubboInvoker中邏輯。

對于異步請求時殖属,消費者得到Future茎毁,其余邏輯均是異步的。

消費者還可以通過設置async忱辅、sent、return來調整處理邏輯谭溉,async指異步還是同步請求墙懂,sent指是否等待請求消息發(fā)出即阻塞等待是否成功發(fā)出請求、return指是否忽略返回值即但方向通信扮念,一般異步時使用以減少Future對象的創(chuàng)建和管理成本损搬。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市柜与,隨后出現的幾起案子巧勤,更是在濱河造成了極大的恐慌,老刑警劉巖弄匕,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件颅悉,死亡現場離奇詭異,居然都是意外死亡迁匠,警方通過查閱死者的電腦和手機剩瓶,發(fā)現死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進店門驹溃,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人延曙,你說我怎么就攤上這事豌鹤。” “怎么了枝缔?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵布疙,是天一觀的道長。 經常有香客問我愿卸,道長灵临,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任擦酌,我火速辦了婚禮俱诸,結果婚禮上,老公的妹妹穿的比我還像新娘赊舶。我一直安慰自己睁搭,他們只是感情好,可當我...
    茶點故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布笼平。 她就那樣靜靜地躺著园骆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪寓调。 梳的紋絲不亂的頭發(fā)上锌唾,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天,我揣著相機與錄音夺英,去河邊找鬼晌涕。 笑死,一個胖子當著我的面吹牛痛悯,可吹牛的內容都是我干的余黎。 我是一名探鬼主播,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼载萌,長吁一口氣:“原來是場噩夢啊……” “哼惧财!你這毒婦竟也來了?” 一聲冷哼從身側響起扭仁,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤垮衷,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后乖坠,有當地人在樹林里發(fā)現了一具尸體搀突,經...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年熊泵,在試婚紗的時候發(fā)現自己被綠了描姚。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片涩赢。...
    茶點故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖轩勘,靈堂內的尸體忽然破棺而出筒扒,到底是詐尸還是另有隱情,我是刑警寧澤绊寻,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布花墩,位于F島的核電站,受9級特大地震影響澄步,放射性物質發(fā)生泄漏冰蘑。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一村缸、第九天 我趴在偏房一處隱蔽的房頂上張望祠肥。 院中可真熱鬧,春花似錦梯皿、人聲如沸仇箱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽剂桥。三九已至,卻和暖如春属提,著一層夾襖步出監(jiān)牢的瞬間权逗,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工冤议, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留斟薇,地道東北人。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓恕酸,卻偏偏與公主長得像奔垦,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子尸疆,可洞房花燭夜當晚...
    茶點故事閱讀 43,612評論 2 350

推薦閱讀更多精彩內容