七:服务暴露剖析(二)本地暴露及本地调用

服务暴露

本地服务暴露

在这里插入图片描述

	//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&timestamp=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);
            }
        };
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值