服务暴露
本地服务暴露
//org.apache.dubbo.config.ServiceConfig#exportUrl
private void exportUrl(URL url, List<URL> registryURLs) {
//<dubbo:service id="serviceDemo" interface="com.jiangzheng.course.dubbo.api.service.ServiceDemo" ref="iServiceDemo" scope="local"/>
//获取定义的scope的值
String scope = url.getParameter(SCOPE_KEY);
// 如果scope不等于none
if (!SCOPE_NONE.equalsIgnoreCase(scope)) {
//如果scope值不等于remote
if (!SCOPE_REMOTE.equalsIgnoreCase(scope)) {
//先看本地服务暴露,执行到这里
exportLocal(url);
}
//如果scope值不等于local
if (!SCOPE_LOCAL.equalsIgnoreCase(scope)) {
url = exportRemote(url, registryURLs);
MetadataUtils.publishServiceDefinition(url);
}
}
this.urls.add(url);
}
//org.apache.dubbo.config.ServiceConfig#exportLocal
private void exportLocal(URL url) {
//local: injvm://127.0.0.1/com.jiangzheng.course.dubbo.api.service.ServiceDemo?anyhost=true&application=provider&background=false&bind.ip=30.96.216.202&bind.port=29014&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&interface=com.jiangzheng.course.dubbo.api.service.ServiceDemo&metadata-type=remote&methods=getName,getSelf&pid=67241&release=3.0.4&scope=local&side=provider×tamp=1641457573993
URL local = URLBuilder.from(url)
//LOCAL_PROTOCOL: injvm
//此处定义的协议名称为 injvm
.setProtocol(LOCAL_PROTOCOL)
.setHost(LOCALHOST_VALUE)
.setPort(0)
.build();
local = local.setScopeModel(getScopeModel())
.setServiceModel(providerModel);
//执行到这里
doExportUrl(local, false);
logger.info("Export dubbo service " + interfaceClass.getName() + " to local registry url : " + local);
}
private void doExportUrl(URL url, boolean withMetaData) {
//先看这里,此处调用后 会返回一个 com.jiangzheng.course.dubbo.api.service.ServiceDemo的代理类
Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, url);
if (withMetaData) {
invoker = new DelegateProviderMetaDataInvoker(invoker, this);
}
//在执行到这里 调用org.apache.dubbo.rpc.protocol.injvm.InjvmProtocol#export
//InjvmExporter(AbstractProxyInvoker(实体类或者代理类))
Exporter<?> exporter = protocolSPI.export(invoker);
exporters.add(exporter);
}
@SPI(value = "javassist", scope = FRAMEWORK)
public interface ProxyFactory {
}
///Users/wangwenyong/repository/org/apache/dubbo/dubbo/3.0.4/dubbo-3.0.4.jar!/META-INF/dubbo/internal/org.apache.dubbo.rpc.ProxyFactory
stub=org.apache.dubbo.rpc.proxy.wrapper.StubProxyFactoryWrapper
jdk=org.apache.dubbo.rpc.proxy.jdk.JdkProxyFactory
javassist=org.apache.dubbo.rpc.proxy.javassist.JavassistProxyFactory
根据spi定义 我们找到了proxyFactory的实现类 --> JavassistProxyFactory.java
//org.apache.dubbo.rpc.proxy.javassist.JavassistProxyFactory#getInvoker
@Override
public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
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);
}
};
}
//org.apache.dubbo.rpc.protocol.injvm.InjvmProtocol#export
@Override
public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
return new InjvmExporter<T>(invoker, invoker.getUrl().getServiceKey(), exporterMap);
}
//org.apache.dubbo.rpc.protocol.injvm.InjvmExporter#InjvmExporter
InjvmExporter(Invoker<T> invoker, String key, Map<String, Exporter<?>> exporterMap) {
super(invoker);
this.key = key;
this.exporterMap = exporterMap;
//加入到缓存里面
exporterMap.put(key, this);
}
本地服务调用
InvokerInvocationHandler.java是所有调用的入口类
public class InvokerInvocationHandler implements InvocationHandler {
private static final Logger logger = LoggerFactory.getLogger(InvokerInvocationHandler.class);
private final Invoker<?> invoker;
private ServiceModel serviceModel;
private URL url;
private String protocolServiceKey;
public static Field stackTraceField;
static {
try {
stackTraceField = Throwable.class.getDeclaredField("stackTrace");
stackTraceField.setAccessible(true);
} catch (NoSuchFieldException e) {
// ignore
}
}
public InvokerInvocationHandler(Invoker<?> handler) {
this.invoker = handler;
this.url = invoker.getUrl();
this.protocolServiceKey = this.url.getProtocolServiceKey();
this.serviceModel = this.url.getServiceModel();
}
//方法入口
@Override
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, invoker.getInterface().getName(), protocolServiceKey, args);
String serviceKey = url.getServiceKey();
rpcInvocation.setTargetServiceUniqueName(serviceKey);
// invoker.getUrl() returns consumer url.
RpcServiceContext.setRpcContext(url);
if (serviceModel instanceof ConsumerModel) {
rpcInvocation.put(Constants.CONSUMER_MODEL, serviceModel);
rpcInvocation.put(Constants.METHOD_MODEL, ((ConsumerModel) serviceModel).getMethodModel(method));
}
//执行此处 进行方法调用
return invoker.invoke(rpcInvocation).recreate();
}
}
//org.apache.dubbo.rpc.protocol.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 (isDestroyed()) {
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 invocation = (RpcInvocation) inv;
// 准备rpc调用
prepareInvocation(invocation);
// 执行到此处, 调用rpc调用并返回异步结果
AsyncRpcResult asyncResult = doInvokeAndReturn(invocation);
// 如果同步,请等待rpc结果
waitForResultIfSync(asyncResult, invocation);
return asyncResult;
}
//org.apache.dubbo.rpc.protocol.AbstractInvoker#doInvokeAndReturn
private AsyncRpcResult doInvokeAndReturn(RpcInvocation invocation) {
AsyncRpcResult asyncResult;
try {
//执行到这里
asyncResult = (AsyncRpcResult) doInvoke(invocation);
} catch (InvocationTargetException e) {
Throwable te = e.getTargetException();
if (te != null) {
// if biz exception
if (te instanceof RpcException) {
((RpcException) te).setCode(RpcException.BIZ_EXCEPTION);
}
asyncResult = AsyncRpcResult.newDefaultAsyncResult(null, te, invocation);
} else {
asyncResult = AsyncRpcResult.newDefaultAsyncResult(null, e, invocation);
}
} catch (RpcException e) {
// if biz exception
if (e.isBiz()) {
asyncResult = AsyncRpcResult.newDefaultAsyncResult(null, e, invocation);
} else {
throw e;
}
} catch (Throwable e) {
asyncResult = AsyncRpcResult.newDefaultAsyncResult(null, e, invocation);
}
// set server context
RpcContext.getServiceContext().setFuture(new FutureAdapter<>(asyncResult.getResponseFuture()));
return asyncResult;
}
//org.apache.dubbo.rpc.protocol.injvm.InjvmInvoker#doInvoke
@Override
public Result doInvoke(Invocation invocation) throws Throwable {
//从内存中获取对应的exporter
Exporter<?> exporter = InjvmProtocol.getExporter(exporterMap, getUrl());
if (exporter == null) {
throw new RpcException("Service [" + key + "] not found.");
}
//LOCALHOST_VALUE: 127.0.0.1 设置为本地地址
RpcContext.getServiceContext().setRemoteAddress(LOCALHOST_VALUE, 0);
// Solve local exposure, the server opens the token, and the client call fails.
Invoker<?> invoker = exporter.getInvoker();
URL serverURL = invoker.getUrl();
boolean serverHasToken = serverURL.hasParameter(Constants.TOKEN_KEY);
if (serverHasToken) {
invocation.setAttachment(Constants.TOKEN_KEY, serverURL.getParameter(Constants.TOKEN_KEY));
}
String desc = ReflectUtils.getDesc(invocation.getParameterTypes());
// recreate invocation ---> deep copy parameters
Invocation copiedInvocation = recreateInvocation(invocation, invoker, desc);
//是否异步执行
if (isAsync(invoker.getUrl(), getUrl())) {
((RpcInvocation) copiedInvocation).setInvokeMode(InvokeMode.ASYNC);
// use consumer executor
ExecutorService executor = executorRepository.createExecutorIfAbsent(getUrl());
CompletableFuture<AppResponse> appResponseFuture = CompletableFuture.supplyAsync(() -> {
Result result = invoker.invoke(copiedInvocation);
if (result.hasException()) {
return new AppResponse(result.getException());
} else {
rebuildValue(invocation, desc, result);
return new AppResponse(result.getValue());
}
}, executor);
// 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, copiedInvocation);
result.setExecutor(executor);
return result;
} else {
//同步执行到这里
Result result = invoker.invoke(copiedInvocation);
if (result.hasException()) {
return result;
} else {
rebuildValue(invocation, desc, result);
return result;
}
}
}
//org.apache.dubbo.rpc.proxy.AbstractProxyInvoker#invoke
@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(invocation);
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.getServiceContext().isAsyncStarted() && !RpcContext.getServiceContext().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);
}
}
//org.apache.dubbo.rpc.proxy.javassist.JavassistProxyFactory#getInvoker
@Override
public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
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);
}
};
}