Dubbo学习记录(十九)-服务调用【五】 - 服务消费者调用流程分析;_dubbo invokerinvocationhandler

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取


### 服务消费端调用流程


#### 1. InvokerInvocationHandler#invoke


* 拦截定义在 Object 类中的方法(未被子类重写),比如 wait/notify
* 判断方法名是否为toString, 是直接调用toString方法, 不需要远程调用
* 判断方法名是否为hashCode, 是直接调用hashCode方法 不需要远程调用
* 判断方法名是否为equals, 是直接调用equals方法; 不需要远程调用
* 都不是,invoker.invoke(new RpcInvocation(method, args))发起远程调用;



public class InvokerInvocationHandler implements InvocationHandler {
private static final Logger logger = LoggerFactory.getLogger(InvokerInvocationHandler.class);
private final Invoker<?> invoker;

public InvokerInvocationHandler(Invoker<?> handler) {
    this.invoker = handler;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    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]);
    }

    // 这里的recreate方法很重要,他会调用AppResponse的recreate方法,
    // 如果AppResponse对象中存在exception信息,则此方法中会throw这个异常
    return invoker.invoke(new RpcInvocation(method, args)).recreate();
}

}


##### RpcInvocation


该类的属性包含服务调用的参数;


* returnType 设置返回值的类型
* methodName : 调用的方法名;
* parameterTypes : 方法参数类型;
* arguments : 参数值
* invoker : 为空,没有传递;
* attachments : 服务配置的一些相关信息,超时等;



public class RpcInvocation implements Invocation, Serializable {
public RpcInvocation(Method method, Object[] arguments, Map<String, String> attachment) {
this(method.getName(), method.getParameterTypes(), arguments, attachment, null);
//设置返回值的类型;
this.returnType = method.getReturnType();
}

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;
    this.attachments = attachments == null ? new HashMap<String, String>() : attachments;
    this.invoker = invoker;
}

}


因此, 服务端执行服务的时候, RpcInvocation实例包含了服务执行需要的数据;


#### 2. MockClusterInvoker#invoke


InvokerInvocationHandler#invoke中, invoker属性类型为MockClusterInvoker实例;执行一些Mock逻辑;


1. 判断mock配置是否为空,为空,则不执行mock逻辑, 调用下一个Invoker的invoke方法;
2. 不为空, 且是force开头, 调用Mock逻辑doMockInvoke方法,结束远程调用;



public class MockClusterInvoker implements Invoker {
private final Directory directory;
private final Invoker invoker;
@Override
public Result invoke(Invocation invocation) throws RpcException {
Result result = null;

    String value = directory.getUrl().getMethodParameter(invocation.getMethodName(), MOCK_KEY, Boolean.FALSE.toString()).trim();
    if (value.length() == 0 || "false".equalsIgnoreCase(value)) {
        //no mock
        result = this.invoker.invoke(invocation);
    } else if (value.startsWith("force")) {
        //force:direct mock 强制调用Mock逻辑, 直接放回数据;
        result = doMockInvoke(invocation, null);
    } else {
 		//省略部分代码
    }
    return result;
}

}


#### 3.1 AbstractClusterInvoker#invoke


接下来是集群容错功能的Invoker, 默认的FailoverClusterInvoker内部没有定义invoke方法,其继承了AbstractClusterInvoker类中定义了invoke方法, 因此调用的是父类的invoke方法;  
 干了三件事:


1. 获取RpcContext中的attachments设置给RpcInvocation对象;
2. 调用list方法 ,调用路由链从服务目录上,获取合适的Invoker实例invokers ;
3. 初始化并获取负载均衡策略loadbalance;
4. 调用子类FailoverClusterInvoker实现的方法doIoke



@Override
public Result invoke(final Invocation invocation) throws RpcException {
    checkWhetherDestroyed();

    // binding attachments into invocation.
    Map<String, String> contextAttachments = RpcContext.getContext().getAttachments();
    if (contextAttachments != null && contextAttachments.size() != 0) {
        ((RpcInvocation) invocation).addAttachments(contextAttachments);
    }

    List<Invoker<T>> invokers = list(invocation);
    LoadBalance loadbalance = initLoadBalance(invokers, invocation);
    RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);
    return doInvoke(invocation, invokers, loadbalance);
}

#### 3.2 FailoverClusterInvoker#doInvoke


* 根据负载均衡策略,选出一个Invoker执行;
* 第一次正常调用,调用失败,会重试两次, 共调用3次;  
 工作流程:


1. 获取methodName;
2. 获取重试次数, 默认值为2; 会进行+1操作, 因此需要把第一次调用算进去;
3. 调用select方法, 负载均衡选出一个服务;
4. 调用下一个invoker#invoke方法;



public class FailoverClusterInvoker extends AbstractClusterInvoker {
public FailoverClusterInvoker(Directory directory) {
super(directory);
}
@Override
@SuppressWarnings({“unchecked”, “rawtypes”})
public Result doInvoke(Invocation invocation, final List<Invoker> invokers, LoadBalance loadbalance) throws RpcException {
List<Invoker> copyInvokers = invokers;
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.
List<Invoker> invoked = new ArrayList<Invoker>(copyInvokers.size()); // invoked invokers.
Set providers = new HashSet(len);
for (int i = 0; i < len; i++) {
if (i > 0) {
checkWhetherDestroyed();
copyInvokers = list(invocation);
// check again
checkInvokers(copyInvokers, invocation);
}
Invoker 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) {
} catch (Throwable e) {
le = new RpcException(e.getMessage(), e);
} finally {
providers.add(invoker.getUrl().getAddress());
}
}
//异常处理
}

}


下一个Invoker的类型为RegistryDirectory$InvokerDelegate类, 调用InvokerDelegate#invoke方法


#### 4 InvokerDelegate#invoke


InvokerDelegate类没有定义invoke方法, 其继承了InvokerWrapper,其定义了invoke方法;  
 这个代理对象invoke,啥都没干;



private static class InvokerDelegate extends InvokerWrapper {
private URL providerUrl;

    public InvokerDelegate(Invoker<T> invoker, URL url, URL providerUrl) {
        super(invoker, url);
        this.providerUrl = providerUrl;
    }

    public URL getProviderUrl() {
        return providerUrl;
    }

}

public class InvokerWrapper implements Invoker {

private final Invoker<T> invoker;
@Override
public Result invoke(Invocation invocation) throws RpcException {
    return invoker.invoke(invocation);
}

}


#### 5 CallbackRegistrationInvoker#invoke


* ProtocolFilterWrapper生成的Invoker;
* 会调用执行过滤器链, 执行完执行完得到结果;
* 拿到结果后,会获取ListenableFilter中的listener,执行listener的onResponse方法



static class CallbackRegistrationInvoker<T> implements Invoker<T> {

    private final Invoker<T> filterInvoker;
    private final List<Filter> filters;

    @Override
    public Result invoke(Invocation invocation) throws RpcException {
        // 执行过滤器链
        Result asyncResult = filterInvoker.invoke(invocation);

        // 过滤器都执行完了之后,回调每个过滤器的onResponse或onError方法
        asyncResult = asyncResult.whenCompleteWithContext((r, t) -> {
            for (int i = filters.size() - 1; i >= 0; i--) {
                Filter filter = filters.get(i);
                // onResponse callback
                if (filter instanceof ListenableFilter) {
                    Filter.Listener listener = ((ListenableFilter) filter).listener();
                    if (listener != null) {
                        if (t == null) {
                            listener.onResponse(r, filterInvoker, invocation);
                        } else {
                            listener.onError(t, filterInvoker, invocation);
                        }
                    }
                } else {
                    filter.onResponse(r, filterInvoker, invocation);
                }
            }
        });
        return asyncResult;
    }

}


#### 5 ConsumerContextFilter#invoke


设置上下文参数;


* 本地地址localAddress;
* 远程调用地址remoteAddress
* 远程应用名称remoteApplicationName;
* 服务参数attachments;



@Activate(group = CONSUMER, order = -10000)
public class ConsumerContextFilter extends ListenableFilter {
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
// 设置RpcContext参数
RpcContext.getContext()
.setInvoker(invoker)
.setInvocation(invocation)
.setLocalAddress(NetUtils.getLocalHost(), 0)
.setRemoteAddress(invoker.getUrl().getHost(), invoker.getUrl().getPort())
.setRemoteApplicationName(invoker.getUrl().getParameter(REMOTE_APPLICATION_KEY))
.setAttachment(REMOTE_APPLICATION_KEY, invoker.getUrl().getParameter(APPLICATION_KEY));
if (invocation instanceof RpcInvocation) {
((RpcInvocation) invocation).setInvoker(invoker);
}
try {
RpcContext.removeServerContext();
return invoker.invoke(invocation);
} finally {
RpcContext.removeContext();
}
}

static class ConsumerContextListener implements Listener {
    @Override
    public void onResponse(Result appResponse, Invoker<?> invoker, Invocation invocation) {
        RpcContext.getServerContext().setAttachments(appResponse.getAttachments());
    }
	//....
}

}


#### 6. FutureFilter#invoke


1. 调用fireInvokeCallback判断是否有回调方法,有就触发回调方法
2. 调用下一个Invoke#invoke处理;



@Activate(group = CommonConstants.CONSUMER)
public class FutureFilter extends ListenableFilter {
@Override
public Result invoke(final Invoker<?> invoker, final Invocation invocation) throws RpcException {
fireInvokeCallback(invoker, invocation);
// need to configure if there’s return value before the invocation in order to help invoker to judge if it’s
// necessary to return future.
return invoker.invoke(invocation);
}
}


#### 7. ListenerInvokerWrapper#invoke


啥都没干,调用下一个Invoker#invoke方法;



public class ListenerInvokerWrapper implements Invoker {
private final Invoker invoker;
private final List listeners;
@Override
public Result invoke(Invocation invocation) throws RpcException {
// AsyncToSyncInvoker
return invoker.invoke(invocation);
}

}


#### 8. AsyncToSyncInvoker#invoke



public class AsyncToSyncInvoker implements Invoker {

private Invoker<T> invoker;

public AsyncToSyncInvoker(Invoker<T> invoker) {
    this.invoker = invoker;
}

@Override
public Class<T> getInterface() {
    return invoker.getInterface();
}

@Override
public Result invoke(Invocation invocation) throws RpcException {
    // 异步转同步

    Result asyncResult = invoker.invoke(invocation);  // AsyncRpcResult--->CompletableFuture

    try {
        // 如果invocation指定是同步的,则阻塞等待结果
        if (InvokeMode.SYNC == ((RpcInvocation) invocation).getInvokeMode()) {
            asyncResult.get(Integer.MAX_VALUE, TimeUnit.MILLISECONDS);
        }
    } catch (InterruptedException e) {
	//..异常处理
    } catch (Throwable e) {
        throw new RpcException(e.getMessage(), e);
    }
    return asyncResult;
}

}


#### 9. AbstractInvoker.invoke(invocation)


主要调用DubboInvoker的doInvoke方法,如果doInvoker方法出现了异常,会进行包装,包装成AsyncRpcResult



@Override
public Result invoke(Invocation inv) throws RpcException {
    RpcInvocation invocation = (RpcInvocation) inv;
    invocation.setInvoker(this);

    invocation.setInvokeMode(RpcUtils.getInvokeMode(url, invocation));
    RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);

    try {
        return doInvoke(invocation);
    } catch (InvocationTargetException e) { // biz exception
        Throwable te = e.getTargetException();
        if (te == null) {
            return AsyncRpcResult.newDefaultAsyncResult(null, e, invocation);
        } else {
            if (te instanceof RpcException) {
                ((RpcException) te).setCode(RpcException.BIZ_EXCEPTION);
            }

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

{
if (te instanceof RpcException) {
((RpcException) te).setCode(RpcException.BIZ_EXCEPTION);
}

[外链图片转存中…(img-HamVm6uz-1715744524593)]
[外链图片转存中…(img-UV272s86-1715744524593)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值