zoukankan      html  css  js  c++  java
  • Dubbo中服务消费者和服务提供者之间的请求和响应过程

    服务提供者初始化完成之后,对外暴露Exporter。服务消费者初始化完成之后,得到的是Proxy代理,方法调用的时候就是调用代理。服务消费者经过初始化之后,得到的是一个动态代理类,InvokerInvocationHandler,包含MockClusterInvoker,MockClusterInvoker包含一个RegistryDirectory和FailoverClusterInvoker。Java动态代理,每一个动态代理类都必须要实现InvocationHandler这个接口,并且每一个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法就会被转发为由实现了InvocationHandler这个接口的类的invoke方法来进行调用。
    服务消费者发起调用请求
    InvokerInvocationHandler实现了InvocationHandler接口,当我们调用helloService.sayHello();的时候,实际上会调用invoke()方法:

      //proxy是代理的真实对象
      //method调用真实对象的方法
      //args调用真实对象的方法的参数
      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if (method.getDeclaringClass() == Object.class) {
                return method.invoke(invoker, args);
            }
            //方法名sayHello
            String methodName = method.getName();
            //参数类型
            Class<?>[] parameterTypes = method.getParameterTypes();
            if (parameterTypes.length == 0) {
                if ("toString".equals(methodName)) {
                    return invoker.toString();
                } else if ("$destroy".equals(methodName)) {
                    invoker.destroy();
                    return null;
                } else if ("hashCode".equals(methodName)) {
                    return invoker.hashCode();
                }
            } else if (parameterTypes.length == 1 && "equals".equals(methodName)) {
                return invoker.equals(args[0]);
            }
            RpcInvocation rpcInvocation = new RpcInvocation(method, invoker.getInterface().getName(), protocolServiceKey, args);
            String serviceKey = invoker.getUrl().getServiceKey();
            rpcInvocation.setTargetServiceUniqueName(serviceKey);
    
            // invoker.getUrl() returns consumer url.
            RpcContext.setRpcContext(invoker.getUrl());
    
            if (consumerModel != null) {
                rpcInvocation.put(Constants.CONSUMER_MODEL, consumerModel);
                rpcInvocation.put(Constants.METHOD_MODEL, consumerModel.getMethodModel(method));
            }
    
            return invoker.invoke(rpcInvocation).recreate();
        }

    先看下new RpcInvocation,Invocation是会话域,它持有调用过程中的变量,比如方法名,参数类型等。
    接着是invoker.invoke(),这里invoker是MockClusterInvoker,进入MockClusterInvoker.invoker():

        @Override
        public Result invoke(Invocation invocation) throws RpcException {
            if (invocation instanceof RpcInvocation) {
                ((RpcInvocation) invocation).setInvoker(this);
            }
            String mock = null;
            if (getUrl().hasMethodParameter(invocation.getMethodName())) {
                mock = getUrl().getParameter(in vocation.getMethodName() + "." + MOCK_KEY);
            }
            if (StringUtils.isBlank(mock)) {
                mock = getUrl().getParameter(MOCK_KEY);
            }
    
            if (StringUtils.isBlank(mock)) {
                throw new RpcException(new IllegalAccessException("mock can not be null. url :" + url));
            }
            mock = normalizeMock(URL.decode(mock));
            if (mock.startsWith(RETURN_PREFIX)) {
                mock = mock.substring(RETURN_PREFIX.length()).trim();
                try {
                    Type[] returnTypes = RpcUtils.getReturnTypes(invocation);
                    Object value = parseMockValue(mock, returnTypes);
                    return AsyncRpcResult.newDefaultAsyncResult(value, invocation);
                } catch (Exception ew) {
                    throw new RpcException("mock return invoke error. method :" + invocation.getMethodName()
                            + ", mock:" + mock + ", url: " + url, ew);
                }
            } else if (mock.startsWith(THROW_PREFIX)) {
                mock = mock.substring(THROW_PREFIX.length()).trim();
                if (StringUtils.isBlank(mock)) {
                    throw new RpcException("mocked exception for service degradation.");
                } else { // user customized class
                    Throwable t = getThrowable(mock);
                    throw new RpcException(RpcException.BIZ_EXCEPTION, t);
                }
            } else { //impl mock
                try {
                    Invoker<T> invoker = getInvoker(mock);
                    return invoker.invoke(invocation);
                } catch (Throwable t) {
                    throw new RpcException("Failed to create mock implementation class " + mock, t);
                }
            }
        }

    result = this.invoker.invoke(invocation);这里invoker是FailoverClusterInvoker,会首先进入AbstractClusterInvoker的invoke方法:

        @Override
        public Result invoke(final Invocation invocation) throws RpcException {
            //检查是否被销毁
            checkWhetherDestroyed();
    
            // binding attachments into invocation.
            Map<String, Object> contextAttachments = RpcContext.getContext().getObjectAttachments();
            if (contextAttachments != null && contextAttachments.size() != 0) {
                ((RpcInvocation) invocation).addObjectAttachments(contextAttachments);
            }
    
            //根据invocation中的参数来获取所有的invoker列表
            List<Invoker<T>> invokers = list(invocation);
            //我们没有配置负载均衡的参数,默认使用random
            //这里得到的是RandomLoadBalance
            LoadBalance loadbalance = initLoadBalance(invokers, invocation);
            //如果是异步操作默认添加invocation id
            RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);
            //这里是子类实现,FailoverClusterInvoker中,执行调用
            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);
            String methodName = RpcUtils.getMethodName(invocation);
            //重试次数
            int len = getUrl().getMethodParameter(methodName, RETRIES_KEY, 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++) {
                //Reselect before retry to avoid a change of candidate `invokers`.
                //NOTE: if `invokers` changed, then `invoked` also lose accuracy.
                //重试时,进行重新选择,避免重试时invoker列表已发生变化.
                //注意:如果列表发生了变化,那么invoked判断会失效,因为invoker示例已经改变
                if (i > 0) {
                    checkWhetherDestroyed();
                    copyInvokers = list(invocation);
                    // check again
                    //重新检查一下
                    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);
                    if (le != null && logger.isWarnEnabled()) {
                        logger.warn("Although retry the method " + methodName
                                + " in the service " + getInterface().getName()
                                + " was successful by the provider " + invoker.getUrl().getAddress()
                                + ", but there have been failed providers " + providers
                                + " (" + providers.size() + "/" + copyInvokers.size()
                                + ") from the registry " + directory.getUrl().getAddress()
                                + " on the consumer " + NetUtils.getLocalHost()
                                + " using the dubbo version " + Version.getVersion() + ". Last error is: "
                                + le.getMessage(), le);
                    }
                    return result;
                } catch (RpcException e) {
                    if (e.isBiz()) { // biz exception.
                        throw e;
                    }
                    le = e;
                } catch (Throwable e) {
                    le = new RpcException(e.getMessage(), e);
                } finally {
                    providers.add(invoker.getUrl().getAddress());
                }
            }
            throw new RpcException(le.getCode(), "Failed to invoke the method "
                    + methodName + " in the service " + getInterface().getName()
                    + ". Tried " + len + " times of the providers " + providers
                    + " (" + providers.size() + "/" + copyInvokers.size()
                    + ") from the registry " + directory.getUrl().getAddress()
                    + " on the consumer " + NetUtils.getLocalHost() + " using the dubbo version "
                    + Version.getVersion() + ". Last error is: "
                    + le.getMessage(), le.getCause() != null ? le.getCause() : le);
        }

    Result result = invoker.invoke(invocation);调用并返回结果,会首先进入InvokerWrapper,然后进入ListenerInvokerWrapper的invoke方法,接着进入AbstractInvoker的invoke:

      @Override
        public Result invoke(Invocation inv) throws RpcException {
            // if invoker is destroyed due to address refresh from registry, let's allow the current invoke to proceed
            if (destroyed.get()) {
                logger.warn("Invoker for service " + this + " on consumer " + NetUtils.getLocalHost() + " is destroyed, "
                        + ", dubbo version is " + Version.getVersion() + ", this invoker should not be used any longer");
            }
            //转成RpcInvocation
            RpcInvocation invocation = (RpcInvocation) inv;
            invocation.setInvoker(this);
            if (CollectionUtils.isNotEmptyMap(attachment)) {
                invocation.addObjectAttachmentsIfAbsent(attachment);
            }
    
            Map<String, Object> contextAttachments = RpcContext.getContext().getObjectAttachments();
            if (CollectionUtils.isNotEmptyMap(contextAttachments)) {
                /**
                 * invocation.addAttachmentsIfAbsent(context){@link RpcInvocation#addAttachmentsIfAbsent(Map)}should not be used here,
                 * because the {@link RpcContext#setAttachment(String, String)} is passed in the Filter when the call is triggered
                 * by the built-in retry mechanism of the Dubbo. The attachment to update RpcContext will no longer work, which is
                 * a mistake in most cases (for example, through Filter to RpcContext output traceId and spanId and other information).
                 */
                invocation.addObjectAttachments(contextAttachments);
            }
    
            invocation.setInvokeMode(RpcUtils.getInvokeMode(url, invocation));
            //异步的话,需要添加id
            RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);
    
            AsyncRpcResult asyncResult;
            try {
                asyncResult = (AsyncRpcResult) doInvoke(invocation);
            } catch (InvocationTargetException e) { // biz exception
                Throwable te = e.getTargetException();
                if (te == null) {
                    asyncResult = AsyncRpcResult.newDefaultAsyncResult(null, e, invocation);
                } else {
                    if (te instanceof RpcException) {
                        ((RpcException) te).setCode(RpcException.BIZ_EXCEPTION);
                    }
                    asyncResult = AsyncRpcResult.newDefaultAsyncResult(null, te, invocation);
                }
            } catch (RpcException e) {
                if (e.isBiz()) {
                    asyncResult = AsyncRpcResult.newDefaultAsyncResult(null, e, invocation);
                } else {
                    throw e;
                }
            } catch (Throwable e) {
                asyncResult = AsyncRpcResult.newDefaultAsyncResult(null, e, invocation);
            }
            RpcContext.getContext().setFuture(new FutureAdapter(asyncResult.getResponseFuture()));
            return asyncResult;
        }

    DubboInvoker.doInvoke():

        @Override
        protected Result doInvoke(final Invocation invocation) throws Throwable {
            RpcInvocation inv = (RpcInvocation) invocation;
            final String methodName = RpcUtils.getMethodName(invocation);
            inv.setAttachment(PATH_KEY, getUrl().getPath());
            inv.setAttachment(VERSION_KEY, version);
    
            ExchangeClient currentClient;
            //在初始化的时候,引用服务的过程中会保存一个连接到服务端的Client
            if (clients.length == 1) {
                currentClient = clients[0];
            } else {
                currentClient = clients[index.getAndIncrement() % clients.length];
            }
            try {
                //单向标志
                boolean isOneway = RpcUtils.isOneway(getUrl(), invocation);
                int timeout = calculateTimeout(invocation, methodName);
                invocation.put(TIMEOUT_KEY, timeout);
                //单向的,反送完不管结果
                if (isOneway) {
                    boolean isSent = getUrl().getMethodParameter(methodName, Constants.SENT_KEY, false);
                    currentClient.send(inv, isSent);
                    return AsyncRpcResult.newDefaultAsyncResult(invocation);
                } else {
                    ExecutorService executor = getCallbackExecutor(getUrl(), inv);
                    CompletableFuture<AppResponse> appResponseFuture =
                            currentClient.request(inv, timeout, executor).thenApply(obj -> (AppResponse) obj);
                    // save for 2.6.x compatibility, for example, TraceFilter in Zipkin uses com.alibaba.xxx.FutureAdapter
                    FutureContext.getContext().setCompatibleFuture(appResponseFuture);
                    AsyncRpcResult result = new AsyncRpcResult(appResponseFuture, inv);
                    result.setExecutor(executor);
                    return result;
                }
            } catch (TimeoutException e) {
                throw new RpcException(RpcException.TIMEOUT_EXCEPTION, "Invoke remote method timeout. method: " + invocation.getMethodName() + ", provider: " + getUrl() + ", cause: " + e.getMessage(), e);
            } catch (RemotingException e) {
                throw new RpcException(RpcException.NETWORK_EXCEPTION, "Failed to invoke remote method: " + invocation.getMethodName() + ", provider: " + getUrl() + ", cause: " + e.getMessage(), e);
            }
        }

    我们这里使用的是同步调用,看(Result) currentClient.request(inv, timeout).get();方法,这里的client是ReferenceCountExchangeClient,直接调用HeaderExchangeClient的request方法:

        @Override
        public CompletableFuture<Object> request(Object request, int timeout) throws RemotingException {
            return channel.request(request, timeout);
        }

    进入HeaderExchangeChannel的request方法:

        @Override
        public CompletableFuture<Object> request(Object request, int timeout, ExecutorService executor) throws RemotingException {
            if (closed) {
                throw new RemotingException(this.getLocalAddress(), null, "Failed to send request " + request + ", cause: The channel " + this + " is closed!");
            }
            // create request.
            Request req = new Request();
            req.setVersion(Version.getProtocolVersion());
            req.setTwoWay(true);
            req.setData(request);
            DefaultFuture future = DefaultFuture.newFuture(channel, req, timeout, executor);
            try {
                channel.send(req);
            } catch (RemotingException e) {
                future.cancel();
                throw e;
            }
            return future;
        }

    channel.send(req),首先会调用AbstractPeer的send方法:

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

    AbstractClient执行发送:

        @Override
        public void send(Object message, boolean sent) throws RemotingException {
            //重连
            if (needReconnect && !isConnected()) {
                connect();
            }
            //先获取Channel,是在NettyClient中实现的
            Channel channel = getChannel();
            //TODO Can the value returned by getChannel() be null? need improvement.
            //TODO getChannel返回的状态是否包含null需要改进
            if (channel == null || !channel.isConnected()) {
                throw new RemotingException(this, "message can not send, because channel is closed . url:" + getUrl());
            }
            channel.send(message, sent);
        }

    channel.send(message, sent);首先经过AbstractChannel的send方法处理,只是判断是否关闭了,然后是NettyChannel的send来继续处理,这里就把消息发送到服务端了:

      @Override
        public void send(Object message, boolean sent) throws RemotingException {
            // whether the channel is closed
            super.send(message, sent);
    
            boolean success = true;
            int timeout = 0;
            try {
                //交给netty处理
                ChannelFuture future = channel.writeAndFlush(message);
                if (sent) {
                    // wait timeout ms
                    timeout = getUrl().getPositiveParameter(TIMEOUT_KEY, DEFAULT_TIMEOUT);
                    success = future.await(timeout);
                }
                Throwable cause = future.cause();
                if (cause != null) {
                    throw cause;
                }
            } catch (Throwable e) {
                removeChannelIfDisconnected(channel);
                throw new RemotingException(this, "Failed to send message " + PayloadDropper.getRequestWithoutData(message) + " to " + getRemoteAddress() + ", cause: " + e.getMessage(), e);
            }
            if (!success) {
                throw new RemotingException(this, "Failed to send message " + PayloadDropper.getRequestWithoutData(message) + " to " + getRemoteAddress()
                        + "in timeout(" + timeout + "ms) limit");
            }
        }

    服务提供者处理并响应请求
    服务端已经打开端口并监听请求的到来,当服务消费者发送调用请求的时候,经过Netty的处理后会到dubbo中的codec相关方法中先进行解码,入口是NettyCodecAdapter.messageReceived(),关于这个方法的代码在dubbo编解码的那篇文章中已经分析过,不再重复。经过解码之后,会进入到NettyHandler.messageReceived()方法:

        @Override
        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方法

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

    进入MultiMessageHandler的received方法:

        @Override
        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 {
                handler.received(channel, message);
            }
        }

    进入HeartbeatHandler的received方法:

        @Override
        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(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("Receive heartbeat response in thread " + Thread.currentThread().getName());
                }
                return;
            }
            //这里是AllChannelHandler
            handler.received(channel, message);
        }

    继续进入AllChannelHandler的received方法:

        @Override
        public void received(Channel channel, Object message) throws RemotingException {
           //获取线程池执行
            ExecutorService executor = getPreferredExecutorService(message);
            try {
                //handler是DecodeHandler
                executor.execute(new ChannelEventRunnable(channel, handler, ChannelState.RECEIVED, message));
            } catch (Throwable t) {
                if(message instanceof Request && t instanceof RejectedExecutionException){
                    sendFeedback(channel, (Request) message, t);
                    return;
                }
                throw new ExecutionException(message, channel, getClass() + " error when process received event .", t);
            }
        }

    这里会去启动新线程执行ChannelEventRunnable的run方法,接着去调用DecodeHandler的received方法:

        @Override
        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方法:

      @Override
        public void received(Channel channel, Object message) throws RemotingException {
            final ExchangeChannel exchangeChannel = HeaderExchangeChannel.getOrAddChannel(channel);
            if (message instanceof Request) {
                // handle request.
                //request类型的消息
                Request request = (Request) message;
                if (request.isEvent()) {
                    //判断心跳还是正常请求
                    //    处理心跳
                    handlerEvent(channel, request);
                } else {
                    if (request.isTwoWay()) {
                        //正常的请求
                        //需要返回
                        handleRequest(exchangeChannel, request);
                    } else {
                        handler.received(exchangeChannel, request.getData());
                    }
                }
            } else if (message instanceof 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());
                    logger.error(e.getMessage(), e);
                } else {
                    String echo = handler.telnet(channel, (String) message);
                    if (echo != null && echo.length() > 0) {
                        channel.send(echo);
                    }
                }
            } else {
                handler.received(exchangeChannel, message);
            }
        }

    先看下处理请求,并构造响应信息:

     void handleRequest(final 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);
    
                channel.send(res);
                return;
            }
            // find handler by message class.
            Object msg = req.getData();
            try {
                CompletionStage<Object> future = handler.reply(channel, msg);
                future.whenComplete((appResult, t) -> {
                    try {
                        if (t == null) {
                            res.setStatus(Response.OK);
                            res.setResult(appResult);
                        } 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);
                    }
                });
            } catch (Throwable e) {
                res.setStatus(Response.SERVICE_ERROR);
                res.setErrorMessage(StringUtils.toString(e));
                channel.send(res);
            }
        }

    进入DubboProtocol中的ExchangeHandlerAdapter的replay方法:

     public CompletableFuture<Object> reply(ExchangeChannel channel, Object message) throws RemotingException {
    
                if (!(message instanceof Invocation)) {
                    throw new RemotingException(channel, "Unsupported request: "
                            + (message == null ? null : (message.getClass().getName() + ": " + message))
                            + ", channel: consumer: " + channel.getRemoteAddress() + " --> provider: " + channel.getLocalAddress());
                }
    
                Invocation inv = (Invocation) message;
                Invoker<?> invoker = getInvoker(channel, inv);
                // need to consider backward-compatibility if it's a callback
                if (Boolean.TRUE.toString().equals(inv.getObjectAttachments().get(IS_CALLBACK_SERVICE_INVOKE))) {
                    String methodsStr = invoker.getUrl().getParameters().get("methods");
                    boolean hasMethod = false;
                    if (methodsStr == null || !methodsStr.contains(",")) {
                        hasMethod = inv.getMethodName().equals(methodsStr);
                    } else {
                        String[] methods = methodsStr.split(",");
                        for (String method : methods) {
                            if (inv.getMethodName().equals(method)) {
                                hasMethod = true;
                                break;
                            }
                        }
                    }
                    if (!hasMethod) {
                        logger.warn(new IllegalStateException("The methodName " + inv.getMethodName()
                                + " not found in callback service interface ,invoke will be ignored."
                                + " please update the api interface. url is:"
                                + invoker.getUrl()) + " ,invocation is :" + inv);
                        return null;
                    }
                }
                RpcContext.getContext().setRemoteAddress(channel.getRemoteAddress());
                Result result = invoker.invoke(inv);
                return result.thenApply(Function.identity());
            }

    先看下getInvoker获取Invoker:

    Invoker<?> getInvoker(Channel channel, Invocation inv) throws RemotingException {
            boolean isCallBackServiceInvoke = false;
            boolean isStubServiceInvoke = false;
            int port = channel.getLocalAddress().getPort();
            String path = (String) inv.getObjectAttachments().get(PATH_KEY);
    
            //如果是客户端的回调服务
            // if it's callback service on client side
            isStubServiceInvoke = Boolean.TRUE.toString().equals(inv.getObjectAttachments().get(STUB_EVENT_KEY));
            if (isStubServiceInvoke) {
                port = channel.getRemoteAddress().getPort();
            }
    
            //callback
            isCallBackServiceInvoke = isClientSide(channel) && !isStubServiceInvoke;
            if (isCallBackServiceInvoke) {
                path += "." + inv.getObjectAttachments().get(CALLBACK_SERVICE_KEY);
                inv.getObjectAttachments().put(IS_CALLBACK_SERVICE_INVOKE, Boolean.TRUE.toString());
            }
    
            String serviceKey = serviceKey(
                    port,
                    path,
                    (String) inv.getObjectAttachments().get(VERSION_KEY),
                    (String) inv.getObjectAttachments().get(GROUP_KEY)
            );
            //从之前缓存的exporterMap中查找Exporter
            DubboExporter<?> exporter = (DubboExporter<?>) exporterMap.get(serviceKey);
    
            if (exporter == null) {
                throw new RemotingException(channel, "Not found exported service: " + serviceKey + " in " + exporterMap.keySet() + ", may be version or group mismatch " +
                        ", channel: consumer: " + channel.getRemoteAddress() + " --> provider: " + channel.getLocalAddress() + ", message:" + getInvocationWithoutData(inv));
            }
    
            //得到Invoker,返回
            return exporter.getInvoker();
        }

    再看执行调用invoker.invoke(inv);,会先进入InvokerWrapper:

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

    接着进入AbstractProxyInvoker:

       @Override
        public Result invoke(Invocation invocation) throws RpcException {
            try {
                Object value = doInvoke(proxy, invocation.getMethodName(), invocation.getParameterTypes(), invocation.getArguments());
                CompletableFuture<Object> future = wrapWithFuture(value);
                CompletableFuture<AppResponse> appResponseFuture = future.handle((obj, t) -> {
                    AppResponse result = new AppResponse();
                    if (t != null) {
                        if (t instanceof CompletionException) {
                            result.setException(t.getCause());
                        } else {
                            result.setException(t);
                        }
                    } else {
                        result.setValue(obj);
                    }
                    return result;
                });
                return new AsyncRpcResult(appResponseFuture, invocation);
            } catch (InvocationTargetException e) {
                if (RpcContext.getContext().isAsyncStarted() && !RpcContext.getContext().stopAsync()) {
                    logger.error("Provider async started, but got an exception from the original method, cannot write the exception back to consumer because an async result may have returned the new thread.", e);
                }
                return AsyncRpcResult.newDefaultAsyncResult(null, e.getTargetException(), invocation);
            } catch (Throwable e) {
                throw new RpcException("Failed to invoke remote proxy method " + invocation.getMethodName() + " to " + getUrl() + ", cause: " + e.getMessage(), e);
            }
        }

    这里的doInvoke是在JavassistProxyFactory中的AbstractProxyInvoker实例:

        @Override
        public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
            // TODO Wrapper cannot handle this scenario correctly: the classname contains '$'
            // 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,发送响应信息
                        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);
        }
    }

    解析完请求,构造完响应消息,就开始发送响应了,channel.send(response);,先经过AbstractPeer:

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

    进入NettyChannel中,进行响应消息的发送:

      @Override
        public void send(Object message, boolean sent) throws RemotingException {
            // whether the channel is closed
            super.send(message, sent);
    
            boolean success = true;
            int timeout = 0;
            try {
                ChannelFuture future = channel.writeAndFlush(message);
                if (sent) {
                    // wait timeout ms
                    timeout = getUrl().getPositiveParameter(TIMEOUT_KEY, DEFAULT_TIMEOUT);
                    success = future.await(timeout);
                }
                Throwable cause = future.cause();
                if (cause != null) {
                    throw cause;
                }
            } catch (Throwable e) {
                removeChannelIfDisconnected(channel);
                throw new RemotingException(this, "Failed to send message " + PayloadDropper.getRequestWithoutData(message) + " to " + getRemoteAddress() + ", cause: " + e.getMessage(), e);
            }
            if (!success) {
                throw new RemotingException(this, "Failed to send message " + PayloadDropper.getRequestWithoutData(message) + " to " + getRemoteAddress()
                        + "in timeout(" + timeout + "ms) limit");
            }
        }

    消费者接受到服务端返回的响应后的处理
    服务提供者端接收到消费者端的请求并处理之后,返回给消费者端,消费者这边接受响应的入口跟提供者差不多,也是NettyCodecAdapter.messageReceived(),经过解码,到NettyHandler.messageReceived()处理:

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

    先经过AbstractPeer的received方法:

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

    进入MultiMessageHandler:

        @Override
        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 {
                handler.received(channel, message);
            }
        }

    进入HeartbeatHandler,根据不同类型进行处理:

    @Override
        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(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("Receive heartbeat response in thread " + Thread.currentThread().getName());
                }
                return;
            }
            handler.received(channel, message);
        }

    进入AllChannelHandler:

        @Override
        public void received(Channel channel, Object message) throws RemotingException {
            ExecutorService executor = getPreferredExecutorService(message);
            try {
                executor.execute(new ChannelEventRunnable(channel, handler, ChannelState.RECEIVED, message));
            } catch (Throwable t) {
                if(message instanceof Request && t instanceof RejectedExecutionException){
                    sendFeedback(channel, (Request) message, t);
                    return;
                }
                throw new ExecutionException(message, channel, getClass() + " error when process received event .", t);
            }
        }

    然后在新线程,ChannelEventRunnable的run方法中进入DecodeHandler:

        @Override
        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());
            }
    
            handler.received(channel, message);
        }

    进入处理response的decode方法,进行解码response:

        private void decode(Object message) {
            if (message instanceof Decodeable) {
                try {
                    ((Decodeable) message).decode();
                    if (log.isDebugEnabled()) {
                        log.debug("Decode decodeable message " + message.getClass().getName());
                    }
                } catch (Throwable e) {
                    if (log.isWarnEnabled()) {
                        log.warn("Call Decodeable.decode failed: " + e.getMessage(), e);
                    }
                } // ~ end of catch
            } // ~ end of if
        } // ~ end of method decode

    接着会进入HeaderExchangerHandler.received () 方法:

        @Override
        public void received(Channel channel, Object message) throws RemotingException {
            final ExchangeChannel exchangeChannel = HeaderExchangeChannel.getOrAddChannel(channel);
            if (message instanceof Request) {
                // handle request.
                Request request = (Request) message;
                if (request.isEvent()) {
                    handlerEvent(channel, request);
                } else {
                    if (request.isTwoWay()) {
                        handleRequest(exchangeChannel, request);
                    } else {
                        handler.received(exchangeChannel, request.getData());
                    }
                }
            } else if (message instanceof 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());
                    logger.error(e.getMessage(), e);
                } else {
                    String echo = handler.telnet(channel, (String) message);
                    if (echo != null && echo.length() > 0) {
                        channel.send(echo);
                    }
                }
            } else {
                handler.received(exchangeChannel, message);
            }
        }

    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中,这里继续执行,然后执行Filter,最后返回到InvokerInvocationHandler.invoker()方法中,方法得到调用结果,结束!
    注意:
    消费者端的DubboInvoker发起请求后,后续的逻辑是异步的或是指定超时时间内阻塞的,直到得到响应结果后,继续执行DubboInvoker中逻辑。
    对于异步请求时,消费者得到Future,其余逻辑均是异步的。
    消费者还可以通过设置async、sent、return来调整处理逻辑,async指异步还是同步请求,sent指是否等待请求消息发出即阻塞等待是否成功发出请求、return指是否忽略返回值即但方向通信,一般异步时使用以减少Future对象的创建和管理成本。

    参考博客:https://blog.csdn.net/chijunmei7041/article/details/100854806

    郭慕荣博客园
  • 相关阅读:
    前台ajax传数组,后台java接收
    CSS揭秘—打字动效(四)
    通过四个问题了解HTTP协议基础
    Fiddler抓包工具怎么设置HTTPS抓包
    固定定位导致$(window).scrollTop();获取滚动后到顶部距离总是为0
    git bash 使用自带 curl 命令出现乱码解决方法
    移动端布局方案—vw+rem
    Windows安装Nginx需要注意的地方
    orientation属性(判断是否为横竖屏)
    js之瀑布流的实现
  • 原文地址:https://www.cnblogs.com/jelly12345/p/15730492.html
Copyright © 2011-2022 走看看