(1)当消费方调用远程服务的方法时,会被InvokerInvocationHandler拦截,执行其invoke()方法,创建RpcInvocation对象;
(2)接着会获取Invokers以及负载均衡策略;
(3)最后执行DubboInvoker的doInvoke()方法发起远程调用。
服务消费端启动时,会为需要调用的远程服务类创建代理类(通过ReferenceConfig的get()方法),其中代理类的方法拦截器为InvokerInvocationHandler。代码如下所示。
public T getProxy(Invoker invoker, Class>[] interfaces) {
try {
return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
} catch (Throwable fromJavassist) {
// try fall back to JDK proxy factory
try {
T proxy = jdkProxyFactory.getProxy(invoker, interfaces);
logger.error(PROXY_FAILED, "", "", "Failed to generate proxy by Javassist failed. Fallback to use JDK proxy success. " +
"Interfaces: " + Arrays.toString(interfaces), fromJavassist);
return proxy;
} catch (Throwable fromJdk) {
logger.error(PROXY_FAILED, "", "", "Failed to generate proxy by Javassist failed. Fallback to use JDK proxy is also failed. " +
"Interfaces: " + Arrays.toString(interfaces) + " Javassist Error.", fromJavassist);
logger.error(PROXY_FAILED, "", "", "Failed to generate proxy by Javassist failed. Fallback to use JDK proxy is also failed. " +
"Interfaces: " + Arrays.toString(interfaces) + " JDK Error.", fromJdk);
throw fromJavassist;
}
}
}
所以,当消费方调用远程服务的方法时,会被InvokerInvocationHandler拦截,执行其invoke()方法。其中method为调用的方法,args为参数。此处创建的RpcInvocation对象会一直传递下去,直到发起远程调用。invoke()方法代码如下所示。
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getDeclaringClass() == Object.class) {
return method.invoke(invoker, args);
}
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(serviceModel, method.getName(), invoker.getInterface().getName(), protocolServiceKey, method.getParameterTypes(), args);
if (serviceModel instanceof ConsumerModel) {
rpcInvocation.put(Constants.CONSUMER_MODEL, serviceModel);
rpcInvocation.put(Constants.METHOD_MODEL, ((ConsumerModel) serviceModel).getMethodModel(method));
}
return InvocationUtil.invoke(invoker, rpcInvocation);
}
上述 InvocationUtil.invoke() 方法最终会调用AbstractClusterInvoker(Invoker的子类)的invoke() 方法。在该方法中,会根据负载均衡策略等条件,从所有服务提供者Invoker中选择其中一个Invoker来执行远程调用。具体代码如下所示。
public Result invoke(final Invocation invocation) throws RpcException {
checkWhetherDestroyed();
InvocationProfilerUtils.enterDetailProfiler(invocation, () -> "Router route.");
// 1、获取Invocation对应Invokers(路由)
List> invokers = list(invocation);
InvocationProfilerUtils.releaseDetailProfiler(invocation);
checkInvokers(invokers, invocation);
// 2、获取负载均衡策略。根据url参数找LoadBalance扩展,默认RandomLoadBalance
LoadBalance loadbalance = initLoadBalance(invokers, invocation);
RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);
InvocationProfilerUtils.enterDetailProfiler(invocation, () -> "Cluster " + this.getClass().getName() + " invoke.");
try {
// 3、执行远程调用。子类实现,会有不同的集群容错方式
return doInvoke(invocation, invokers, loadbalance);
} finally {
InvocationProfilerUtils.releaseDetailProfiler(invocation);
}
}
(1)Dubbo源码之rpc的调用流程分析