dubbo源码-consumer发送请求-直连

情到浓时终转凉″ 提交于 2019-12-24 09:32:33

下面对调用链的方法进行简要的分析, 疑难的部分会重点分析。同时也会根据 上篇文章 创建代理 的分层逐个进行分析。

直连方式的前半部分

直连方式的后半部分,这部分与订阅方式的后半部分是相同的,所以单独提出来

 

 

consumer发送请求调用链分析

NettyChannel.send(Object, boolean) //调用 NioClientSocketChannel执行write

NettyClient(AbstractClient).send(Object, boolean) /没有连接则创建连接

NettyClient(AbstractPeer).send(Object) //获取 sent 是否等待发送完成

client层:没有连接就创建连接,然后发送数据。

 

HeaderExchangeChannel.request(Object, int)

创建Request,赋值版本,是否双向,请求data(类型 是RpcInvocation),创建DefaultFuture 传入channel,requst实例,超时时间,以request id为key缓存 future,为同步请求,执行future.get()等待响应做准备.

HeaderExchangeClient.request(Object, int) //转发

ReferenceCountExchangeClient.request(Object, int)//转发

交换层:生成请求对象,实现同步等待机制。

 

DubboInvoker<T>.doInvoke(Invocation)//多个client轮询,根据参数 执行 单向,异步,同步请求。

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());//path=tuling.dubbo.server.UserService

inv.setAttachment(Constants.VERSION_KEY, version);//version=0.0.0

ExchangeClient currentClient;

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) {//单向执行 不记录future

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));// 将 future 存入当前RpcContext中

return new RpcResult();//返回空结果

} else {//同步执行

RpcContext.getContext().setFuture(null);

return (Result) currentClient.request(inv, timeout).get();//等待响应 get 抛出TimeoutException

}

} catch (TimeoutException e) {//组装 timeout异常信息

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);

}

}

DubboInvoker<T>(AbstractInvoker<T>).invoke(Invocation) //为RpcInvocation添加attachment

   public Result invoke(Invocation inv) throws RpcException {
//...
        RpcInvocation invocation = (RpcInvocation) inv;
        invocation.setInvoker(this);// 更换invoker, type DubboInvoker
        if (attachment != null && attachment.size() > 0) {{interface=tuling.dubbo.server.UserService, timeout=2147483647}
            invocation.addAttachmentsIfAbsent(attachment);//添加附加参数
        }
        Map<String, String> context = RpcContext.getContext().getAttachments();
        if (context != null) {// context 是空的
            invocation.addAttachmentsIfAbsent(context);
        }
        if (getUrl().getMethodParameter(invocation.getMethodName(), Constants.ASYNC_KEY, false)) {//如果配置了异步,invocation 附加参数添加异步key
            invocation.setAttachment(Constants.ASYNC_KEY, Boolean.TRUE.toString());
        }
        RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);//如果配置了异步,添加执行ID。


        try {
            return doInvoke(invocation);
        } catch (InvocationTargetException e) { // biz exception
//反射异常需要特殊处理
            Throwable te = e.getTargetException();
            if (te == null) {
                return new RpcResult(e);
            } else {
                if (te instanceof RpcException) {
                    ((RpcException) te).setCode(RpcException.BIZ_EXCEPTION);
                }
                return new RpcResult(te);
            }
        } catch (RpcException e) {//自定义异常处理
            if (e.isBiz()) {
                return new RpcResult(e);
            } else {
                throw e;
            }
        } catch (Throwable e) {//未知异常 封装并返回。
            return new RpcResult(e);
        }
    }	

协议层:多个client轮询,实现 单向,异步,同步请求。

 

ListenerInvokerWrapper<T>.invoke(Invocation)//转发

FutureFilter.invoke(Invoker<?>, Invocation) //尾端调用链,执行invoke(),同步或异步执行回调,或抛出异常

ProtocolFilterWrapper$1.invoke(Invocation)//

MonitorFilter.invoke(Invoker<?>, Invocation)//获取监控数据

ProtocolFilterWrapper$1.invoke(Invocation) //filter链 处理

ConsumerContextFilter.invoke(Invoker<?>, Invocation) //记录了 执行context 方便监控获取

ProtocolFilterWrapper$1.invoke(Invocation):调用链实现

过滤链层总结:

FutureFilter:尾端调用链,执行invoke(),同步或异步执行回调,或抛出异常

MonitorFilter:获取监控数据

ConsumerContextFilter:记录了 执行context 方便监控获取

 

InvokerInvocationHandler.invoke(Object, Method, Object[])

动态代理handler执行方法,获取方法名和参数创建RpcInvocation

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

String methodName = method.getName();

Class<?>[] parameterTypes = method.getParameterTypes();

if (method.getDeclaringClass() == Object.class) {//如果方法所属的类是Object ,不执行远程请求,执行Object原本的方法

return method.invoke(invoker, args);

}//如果 是toString,hashCode,equals 这些方法,执行本地方法

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]);

}

return invoker.invoke(new RpcInvocation(method, args)).recreate();

}

RpcInvocation构造方法分析

创建执行参数数据对象。

public RpcInvocation(String methodName, Class<?>[] parameterTypes, Object[] arguments, Map<String, String> attachments, Invoker<?> invoker) {

this.methodName = methodName;//方法名

this.parameterTypes = parameterTypes == null ? new Class<?>[0] : parameterTypes;//参数类型

this.arguments = arguments == null ? new Object[0] : arguments;//参数object

this.attachments = attachments == null ? new HashMap<String, String>() : attachments;//附加参数 赋值空map

this.invoker = invoker;// invoker ==null

}

创建RpcInvocation,存入 方法名,参数类型,参数数组。附加参数 赋值空map,invoker ==null。

动态代理层:获取方法名和参数创建执行参数数据对象

异常处理分析

交换层和client层抛出RemotingException,异常由NettyChannel.send(Object, boolean) 产生

DubboInvoker<T>.doInvoke(Invocation) 将 RemotingException封装成RpcException

发送数据 NettyHandler 写事件处理

DubboProtocol$1(ChannelHandlerAdapter).sent(Channel, Object)

HeaderExchangeHandler.sent(Channel, Object)

DecodeHandler(AbstractChannelHandlerDelegate).sent(Channel, Object)

AllChannelHandler(WrappedChannelHandler).sent(Channel, Object)

HeartbeatHandler.sent(Channel, Object) line: 59

MultiMessageHandler(AbstractChannelHandlerDelegate).sent(Channel, Object)

NettyClient(AbstractPeer).sent(Channel, Object) line: 139

NettyHandler.writeRequested(ChannelHandlerContext, MessageEvent)

层层调用 最后啥也没干

 

精华总结:

client层:没有连接就创建连接,然后发送数据。

交换层:生成请求对象,实现同步等待机制。

协议层:多个client轮询,实现 单向,异步,同步请求。

过滤链层总结:

  FutureFilter:尾端调用链,执行invoke(),同步或异步执行回调,或抛出异常

  MonitorFilter:获取监控数据

  ConsumerContextFilter:记录了 执行context 方便监控获取

动态代理层:获取方法名和参数创建执行参数数据对象

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!