dubbo 4 服务消费者到提供者过程

服务消费者到服务提供者过程
1)首先在初始化nettyServer和nettyClient时候都设置了NettyHandler,那么它的ChannelHandler handler是下面的这条链
MultiMessageHandler->HeartbeatHandler->AllChannelHandler->DecodeHandler->HeaderExchangeHandler->DubboProtocol.requestHandler
这个链怎么来的
1、DubboProtocol的initClient(URL url)
   client = Exchangers.connect(url ,requestHandler);
2、Exchangers的ExchangeClient connect(URL url, ExchangeHandler handler)
   getExchanger(url).connect(url, handler);
3、HeaderExchanger的connect
   return new HeaderExchangeClient(Transporters.connect(url, new DecodeHandler(new HeaderExchangeHandler(handler))));
   到这里可以得到最后三节
4、然后到NettyClient的doOpen()
   NettyHandler nettyHandler = new NettyHandler(getUrl(), this);
   传入的是this自己
   new方法传入的handler即为DecodeHandler
5、父方法wrapChannelHandler方法return ChannelHandlers.wrap(handler, url);
6、ChannelHandlers的wrapInternal
   return new MultiMessageHandler(new HeartbeatHandler(ExtensionLoader.getExtensionLoader(Dispatcher.class)
                                        .getAdaptiveExtension().dispatch(handler, url)));
    即可得到上面的链。 

2)消费者调用,消费者端的配置最后得到DubboInvoker,通过代理生成了代理对象,这个时候调用接口即为使用Invoker的invoke方法
1、DubboInvoker的doInvoke方法,即为向服务端发送数据,最后else是最常用的同步处理方式,调用完后线程会阻塞在这里
   
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) {
            	ResponseFuture future = currentClient.request(inv, timeout) ;
                RpcContext.getContext().setFuture(new FutureAdapter<Object>(future));
                return new RpcResult();
            } else {
            	RpcContext.getContext().setFuture(null);
                return (Result) currentClient.request(inv, timeout).get();
            }


2、currentClient.request(inv, timeout)->HeaderExchangeClient.request->HeaderExchangeChannel.request->NettyClient.send->NettyChannel.send
 
public ResponseFuture request(Object request, int timeout) 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("2.0.0");
        req.setTwoWay(true);
        req.setData(request);
        DefaultFuture future = new DefaultFuture(channel, req, timeout);
        try{
            channel.send(req);
        }catch (RemotingException e) {
            future.cancel();
            throw e;
        }
        return future;
    }


这边结束即通过netty把封装的request发送到了服务端,返回了一个DefaultFuture

3)服务生产者端处理,服务端的netty在收到数据时候,触发NettyHandler的messageReceived方法,也就会触发上面的那一条链
1、当走到HeaderExchangeHandler.received时候
   Response response = handleRequest(exchangeChannel, request);
   channel.send(response);
   处理请求,然后把结果写入channel
2、handleRequest->Object result = handler.reply(channel, msg)->DubboProtocol.requestHandler.reply-> return invoker.invoke(inv);
   在服务端暴漏服务时候,会对每个服务生成一个exporter(持有对应的invoker),invoker是使用proxyFactory.getInvoker生成的
   所有的exporter保存在exporterMap中,key是由serviceKey方法确定,在得到invoker后调用invoke会使用反射来处理请求
   
4)服务端处理完成后,将响应写回客户端,就会触发客户端的NettyHandler的messageReceived方法,这里没有讨论编解码
1、当走到HeaderExchangeHandler.received时候
   else if (message instanceof Response) {
       handleResponse(channel, (Response) message);
2、handleResponse
   static void handleResponse(Channel channel, Response response) throws RemotingException {
        if (response != null && !response.isHeartbeat()) {
            DefaultFuture.received(channel, response);
        }
    }


5)DefaultFuture
   这个类中有static final Map<Long, Channel>   CHANNELS
   final Map<Long, DefaultFuture> FUTURES 用来保存所有的响应DefaultFuture,key为请求响应ID
1、在客户端发送结束后调用get方法阻塞线程
   
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();
    }


2、客户端收到响应后需要唤醒阻塞的线程,调用了received方法,这里就根据请求响应ID来找到对应的DefaultFuture,
进而找到对应线程的condition,唤醒后返回结果
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());
        }
    }


猜你喜欢

转载自blog.csdn.net/u013038630/article/details/74352618