五Dubbo服务引用源码分析--2创建远程调用的代理-2.5开启consumer端NettyClient

五Dubbo服务引用源码分析--2创建远程调用的代理-2.5开启consumer端NettyClient

/**…………NettyClient--开启consumer端………… */
此时url=dubbo://192.168.0.100:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demotest-consumer&bean.name=com.alibaba.dubbo.demo.DemoService&check=false&codec=dubbo&dubbo=2.0.2&generic=false&heartbeat=60000&interface=com.alibaba.dubbo.demo.DemoService&methods=getPermissions&organization=dubbox&owner=programmer&pid=75508&qos.enable=false&register.ip=192.168.0.100&remote.timestamp=1672381137107&side=consumer&timestamp=1672387055607
   public NettyClient(final URL url, final ChannelHandler handler) throws RemotingException {
//NC1 wrapChannelHandler(url, handler)-构建handler链
//NC2 super(url,handler)
        super(url, wrapChannelHandler(url, handler));
    }
//NC1 wrapChannelHandler(url, handler)-构建handler链

同provider端

AbstractClient
   protected static ChannelHandler wrapChannelHandler(URL url, ChannelHandler handler) {
        url = ExecutorUtil.setThreadName(url, CLIENT_THREAD_POOL_NAME);
        url = url.addParameterIfAbsent(Constants.THREADPOOL_KEY, Constants.DEFAULT_CLIENT_THREADPOOL);
        return ChannelHandlers.wrap(handler, url);
    }
ChannelHandlers
   public static ChannelHandler wrap(ChannelHandler handler, URL url) {
        return ChannelHandlers.getInstance().wrapInternal(handler, url);
    }

执行后的handler为:

image-20221219201900692

image-20230313124305764
由内到外的ChanelHandler处理链:
DubboProtocol.ExchangeHandlerAdapter
HeaderExchangeHandler主要还是管理连接等。
DecodeHandler主要是对请求进行解码。
AllChannelHandler是主要负责线程管理。
HeartbeatHandler主要负责心跳检测。
MultiMessageHandler主要负责将Dubbo内部定义的多条消息的聚合消息进行拆分处理。
NettyHandler

构造的channelhandler链,同provider端相同。

//NC2 super(url,handler)
 public AbstractClient(URL url, ChannelHandler handler) throws RemotingException {
        super(url, handler);

        send_reconnect = url.getParameter(Constants.SEND_RECONNECT_KEY, false);

        shutdown_timeout = url.getParameter(Constants.SHUTDOWN_TIMEOUT_KEY, Constants.DEFAULT_SHUTDOWN_TIMEOUT);

        // The default reconnection interval is 2s, 1800 means warning interval is 1 hour.
        reconnect_warning_period = url.getParameter("reconnect.waring.period", 1800);

        try {
//NC2.1 doOpen consumer端打开端口
            doOpen();
        } catch (Throwable t) {
            close();
            throw new RemotingException(url.toInetSocketAddress(), null,
                    "Failed to start " + getClass().getSimpleName() + " " + NetUtils.getLocalAddress()
                            + " connect to the server " + getRemoteAddress() + ", cause: " + t.getMessage(), t);
        }
        try {
//NC2.2 connect 连接
            connect();
//NC2.1 doOpen consumer端pipeline、channelHandler配置
NettyClient
   protected void doOpen() throws Throwable {
        NettyHelper.setNettyLoggerFactory();
        bootstrap = new ClientBootstrap(channelFactory); //创建bootstrap启动类
        // config
        // @see org.jboss.netty.channel.socket.SocketChannelConfig
        bootstrap.setOption("keepAlive", true);
        bootstrap.setOption("tcpNoDelay", true);
        bootstrap.setOption("connectTimeoutMillis", getConnectTimeout());
  		//以nettyclient中的handler,创建NettyHandler
        final NettyHandler nettyHandler = new NettyHandler(getUrl(), this);
        bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
            @Override
            public ChannelPipeline getPipeline() {
                NettyCodecAdapter adapter = new NettyCodecAdapter(getCodec(), getUrl(), NettyClient.this);
                ChannelPipeline pipeline = Channels.pipeline();
                pipeline.addLast("decoder", adapter.getDecoder());
                pipeline.addLast("encoder", adapter.getEncoder());
                pipeline.addLast("handler", nettyHandler);
                return pipeline;
            }
        });
    }

doOpen创建netty的启动配置类,然后设置pipeline、添加channelHandler处理器。

/** …………………消费端connect请求…………………*/
//NC2.2 AbstractClient.connect-->NettyClient.doConnect 连接
AbstractClient
  protected void connect() throws RemotingException {
        connectLock.lock();
        try {
            if (isConnected()) {
                return;
            }
            initConnectStatusCheckCommand();
					//连接provider端
            doConnect();
            if (!isConnected()) {
                throw new RemotingException(this, "Failed connect to server " + getRemoteAddress() + " from " + getClass().getSimpleName() + " "
                        + NetUtils.getLocalHost() + " using dubbo version " + Version.getVersion()
                        + ", cause: Connect wait timeout: " + getConnectTimeout() + "ms.");
            } else {
                if (logger.isInfoEnabled()) {
                    logger.info("Successed connect to server " + getRemoteAddress() + " from " + getClass().getSimpleName() + " "
                            + NetUtils.getLocalHost() + " using dubbo version " + Version.getVersion()
                            + ", channel is " + this.getChannel());
                }
            }
            reconnect_count.set(0);
            reconnect_error_log_flag.set(false);
        } catch (RemotingException e) {
            throw e;
        } catch (Throwable e) {
            throw new RemotingException(this, "Failed connect to server " + getRemoteAddress() + " from " + getClass().getSimpleName() + " "
                    + NetUtils.getLocalHost() + " using dubbo version " + Version.getVersion()
                    + ", cause: " + e.getMessage(), e);
        } finally {
            connectLock.unlock();
        }
    }
NettyClient
 @Override
    protected void doConnect() throws Throwable {
        long start = System.currentTimeMillis();
  //bootstrap辅助类连接
  //getConnectAddress()返回InetSocketAddress,其中addr:port为192.168.0.100:20880
        ChannelFuture future = bootstrap.connect(getConnectAddress());	//异步connect连接
        try {
            boolean ret = future.awaitUninterruptibly(getConnectTimeout(), TimeUnit.MILLISECONDS);
//连接成功后,设置channel关注事件为read、write
            if (ret && future.isSuccess()) {
                Channel newChannel = future.getChannel();
                newChannel.setInterestOps(Channel.OP_READ_WRITE);
                try {
                    // Close old channel
                    Channel oldChannel = NettyClient.this.channel; // copy reference
                    if (oldChannel != null) {
                        try {
                            if (logger.isInfoEnabled()) {
                                logger.info("Close old netty channel " + oldChannel + " on create new netty channel " + newChannel);
                            }
                            oldChannel.close();
                        } finally {
                            NettyChannel.removeChannelIfDisconnected(oldChannel);
                        }
                    }
                } finally {
                    if (NettyClient.this.isClosed()) {
                        try {
                            if (logger.isInfoEnabled()) {
                                logger.info("Close new netty channel " + newChannel + ", because the client closed.");
                            }
                            newChannel.close();
                        } finally {
                            NettyClient.this.channel = null;
                            NettyChannel.removeChannelIfDisconnected(newChannel);
                        }
                    } else {
                        NettyClient.this.channel = newChannel;
                    }
                }
            } else if (future.getCause() != null) {
                throw new RemotingException(this, "client(url: " + getUrl() + ") failed to connect to server "
                        + getRemoteAddress() + ", error message is:" + future.getCause().getMessage(), future.getCause());
            } else {
                throw new RemotingException(this, "client(url: " + getUrl() + ") failed to connect to server "
                        + getRemoteAddress() + " client-side timeout "
                        + getConnectTimeout() + "ms (elapsed: " + (System.currentTimeMillis() - start) + "ms) from netty client "
                        + NetUtils.getLocalHost() + " using dubbo version " + Version.getVersion());
            }
        } finally {
            if (!isConnected()) {
                future.cancel();
            }
        }
    }

连接操作中, 使用netty的辅助类bootstrap异步连接;然后根据future判断连接是否成功。连接成功后,将channel关注事件设置为read、write。

//INV2.2 DubboInvoker

然后返回INV2 DubboProtocol.refer

DubboProtocol.refer
    public <T> Invoker<T> refer(Class<T> serviceType, URL url) throws RpcException {
        optimizeSerialization(url);
        // 创建RPC功能的invoker
//INV2.1 getClients(url)
//INV2.2 DubboInvoker
        DubboInvoker<T> invoker = new DubboInvoker<T>(serviceType, url, getClients(url), invokers);//invokers为null
      		//将创建好的invoker加入集合
        invokers.add(invoker);
        return invoker;
    }

此时,创建DubboInvoker,其内的客户端参数如下:

image-20221231171438232

    public DubboInvoker(Class<T> serviceType, URL url, ExchangeClient[] clients, Set<Invoker<?>> invokers) {
        super(serviceType, url, new String[]{Constants.INTERFACE_KEY, Constants.GROUP_KEY, Constants.TOKEN_KEY, Constants.TIMEOUT_KEY});
        this.clients = clients;
        // get version.
        this.version = url.getParameter(Constants.VERSION_KEY, "0.0.0");
        this.invokers = invokers;
    }
//INV1.1 buildInvokerChain--同provider端

然后执行到ProtocolFilterWrapper.refer处,对invoker构造拦截器链。这里过程和provider端相同

ProtocolFilterWrapper
    public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
        if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
            return protocol.refer(type, url);
        }
        return buildInvokerChain(protocol.refer(type, url), Constants.REFERENCE_FILTER_KEY, Constants.CONSUMER);
    }

image-20221231172711004

invoker创建拦截器链后的链式结构,如上:

ConsumerContextFilter->FutureFilter->MonitorFilter->DubboInvoker。

//SUB2.2.2.1.1 toInvokers(invokerUrls)--构造RegistryDirectory$InvokerDelegate

image-20221231173104529

这里,将buildInvokerChain(protocol.refer(type, url)构造的invoker拦截器链,传入serviceType=demoService,providerURL等,构造成InvokerDelegate.

image-20221231173541789

//SUB2.2.2.1.2 toMethodInvokers(newUrlInvokerMap)-略

然后返回//SUB2.2.2.1 refreshInvoker(invokerUrls)。toMethodInvokers方法,是构建method和invoker的对应关系,存入map中

   private void refreshInvoker(List<URL> invokerUrls) {
//SUB2.2.2.1.1 toInvokers(invokerUrls)
            Map<String, Invoker<T>> newUrlInvokerMap = toInvokers(invokerUrls);// Translate url list to Invoker map
//SUB2.2.2.1.2 toMethodInvokers(newUrlInvokerMap)
            Map<String, List<Invoker<T>>> newMethodInvokerMap = toMethodInvokers(newUrlInvokerMap); // Change method 

newUrlInvokerMap是转换成的新的key:invoker的map存储

image-20221231173952691

返回的newMethodInvokerMap,是分析新创建的invoker的map,将其解析为method:invoker对应的map关系存储。代码执行过程略,看其执行结果:

image-20221231174338163

REFER2.2.4 cluster$Adaptive.join(directory)

然后,返回REFER2.2 doRefer

RegistryProtocol
    private <T> Invoker<T> doRefer(Cluster cluster, Registry registry, Class<T> type, URL url) {
//REFER2.2.1 RegistryDirectory
        RegistryDirectory<T> directory = new RegistryDirectory<T>(type, url);
        directory.setRegistry(registry);//zookeeperRegistry
        directory.setProtocol(protocol);//Protocol$Adaptive
  
        // REFER_KEY的全部属性
        Map<String, String> parameters = new HashMap<String, String>(directory.getUrl().getParameters());
  		//构造consumerURL(订阅注册中心的url)--协议头为consumer,路径名称为demoService,参数对为refer服务的参数
  //consumer://192.168.0.101/com.alibaba.dubbo.demo.DemoService?application=demotest-consumer&dubbo=2.0.2&interface=com.alibaba.dubbo.demo.DemoService&methods=getPermissions&organization=dubbox&owner=programmer&pid=57858&qos.enable=false&side=consumer&timestamp=1672287700727
        URL subscribeUrl = new URL(Constants.CONSUMER_PROTOCOL, parameters.remove(Constants.REGISTER_IP_KEY), 0, type.getName(), parameters);
        if (!Constants.ANY_VALUE.equals(url.getServiceInterface())
                && url.getParameter(Constants.REGISTER_KEY, true)) {
//REFER2.2.2 zookeeperRegistry.register
            registry.register(subscribeUrl.addParameters(Constants.CATEGORY_KEY, Constants.CONSUMERS_CATEGORY,
                    Constants.CHECK_KEY, String.valueOf(false)));
        }
//REFER2.2.3 registryDirectory.subscribe
        directory.subscribe(subscribeUrl.addParameter(Constants.CATEGORY_KEY,
                Constants.PROVIDERS_CATEGORY
                        + "," + Constants.CONFIGURATORS_CATEGORY
                        + "," + Constants.ROUTERS_CATEGORY));
//REFER2.2.4 cluster$Adaptive.join(directory)
        Invoker invoker = cluster.join(directory);
//REFER2.2.5 ProviderConsumerRegTable.registerConsumer(invoker, url, subscribeUrl, directory)
        ProviderConsumerRegTable.registerConsumer(invoker, url, subscribeUrl, directory);
        return invoker;
    }

然后,ClusterDirectory 中的多个 Invoker 伪装成一个 Invoker,对上层透明,伪装过程包含了容错逻辑,调用失败后,重试另一个。

此时,初始化并完成subscribe订阅后,刷新过invokers后的RegistryDierctory对象及属性如下:

image-20230313124355591

public class Cluster$Adaptive implements com.alibaba.dubbo.rpc.cluster.Cluster {
    public com.alibaba.dubbo.rpc.Invoker join(com.alibaba.dubbo.rpc.cluster.Directory arg0) throws com.alibaba.dubbo.rpc.RpcException {
        if (arg0 == null) throw new IllegalArgumentException("com.alibaba.dubbo.rpc.cluster.Directory argument == null");
        if (arg0.getUrl() == null) throw new IllegalArgumentException("com.alibaba.dubbo.rpc.cluster.Directory argument getUrl() == null");
      //zookeeper://127.0.0.1:2181/com.alibaba.dubbo.registry.RegistryService?anyhost=true&application=demotest-consumer&bean.name=com.alibaba.dubbo.demo.DemoService&check=false&dubbo=2.0.2&generic=false&interface=com.alibaba.dubbo.demo.DemoService&methods=getPermissions&organization=dubbox&owner=programmer&pid=14888&qos.enable=false&register.ip=192.168.0.101&remote.timestamp=1672381137107&side=consumer&timestamp=1672478114604
        com.alibaba.dubbo.common.URL url = arg0.getUrl();
        String extName = url.getParameter("cluster", "failover");//默认失败重试集群failoverCluster
        if(extName == null) throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.cluster.Cluster) name from url(" + url.toString() + ") use keys([cluster])");
        com.alibaba.dubbo.rpc.cluster.Cluster extension = (com.alibaba.dubbo.rpc.cluster.Cluster)ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.cluster.Cluster.class).getExtension(extName);
//TAG1.3.1 MockClusterWrapper/FailoverCluster.join
        return extension.join(arg0);
    }

image-20221231185858550

可知返回的cluster集群,是一个wrapper机制包裹上MockClusterWrapper的类。

image-20221231185954954

REFER2.2.4.1 MockClusterWrapper.join--创建MockClusterInvoker
  • Cluster是一个通用代理类,会根据URL中的cluster参数值定位到实际的Cluster实现类也就是FailoverCluster。这里用到了@SPI注解,也就是需要ExtensionLoader扩展点加载机制,而该机制在实例化对象时,会在实例化后自动套上Wapper;

  • 但是是集群模式所以需要Dubbo中另外一个核心机制——Mock。Mock可以在测试中模拟服务调用的各种异常情况,还可以实现服务降级。在MockerClusterInvoker中,Dubbo先检查URL中是否存在mock参数。(这个参数可以通过服务治理后台Consumer端的屏蔽和容错进行设置或者直接动态设置mock参数值)如果存在force开头,这不发起远程调用直接执行降级逻辑。如果存在fail开头,则在远程调用异常时才会执行降级逻辑;

  • 可以说注册中心为集群模式时,Invoker就会外面多包裹一层mock逻辑。是通过Wapper机制实现的。最终可以在调用或者重试时,每次都通过Dubbo内部的负载均衡机制选出多个Invoker中的一个进行调用。

public class MockClusterWrapper implements Cluster {
    @Override
    public <T> Invoker<T> join(Directory<T> directory) throws RpcException {
      
        return new MockClusterInvoker<T>(directory,
//TAG1.3.1.1 FailoverCluster.join
                this.cluster.join(directory));
    }

image-20230101165101896

此处,创建MockClusterInvoker对象,该对象内部存储cluster.join(directory)创建的invoker(这个对象是cluster集群对象对directory中的多个invoker对象,包裹了failover逻辑后伪装成一个invoker,其内包含容错逻辑,在调用失败后,选择下一个invoker)。

   public MockClusterInvoker(Directory<T> directory, Invoker<T> invoker) {
        this.directory = directory;
        this.invoker = invoker;
    }
/**……………………………………………………………………………………invoker.invoke调用逻辑……………………………………………………………………………………………………………… */
        @Override
    public Result invoke(Invocation invocation) throws RpcException {
        Result result = null;

        String value = directory.getUrl().getMethodParameter(invocation.getMethodName(), Constants.MOCK_KEY, Boolean.FALSE.toString()).trim();
  /**………………………………………………………………方法参数中不包含force/fail,正常调用…………………………………………………… */
        if (value.length() == 0 || value.equalsIgnoreCase("false")) {
            //转发给内部的invoker类,调用
            result = this.invoker.invoke(invocation);
        } 
  /**………………………………………………………………方法参数中包含force--不调用,直接服务降级…………………………………………………… */
      else if (value.startsWith("force")) {
            if (logger.isWarnEnabled()) {
                logger.info("force-mock: " + invocation.getMethodName() + " force-mock enabled , url : " + directory.getUrl());
            }
            //force:direct mock
            result = doMockInvoke(invocation, null);
        } 
  /**………………………………………………………………方法参数中包含fail--调用失败,服务降级处理…………………………………………………… */
      else {
            //fail-mock
            try {
                result = this.invoker.invoke(invocation);
            } catch (RpcException e) {
                if (e.isBiz()) {
                    throw e;
                } else {
                    if (logger.isWarnEnabled()) {
                        logger.warn("fail-mock: " + invocation.getMethodName() + " fail-mock enabled , url : " + directory.getUrl(), e);
                    }
                    result = doMockInvoke(invocation, e);
                }
            }
        }
        return result;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    private Result doMockInvoke(Invocation invocation, RpcException e) {
        Result result = null;
        Invoker<T> minvoker;

        List<Invoker<T>> mockInvokers = selectMockInvoker(invocation);
        if (mockInvokers == null || mockInvokers.isEmpty()) {
            minvoker = (Invoker<T>) new MockInvoker(directory.getUrl());
        } else {
            minvoker = mockInvokers.get(0);
        }
        try {
            result = minvoker.invoke(invocation);
        } catch (RpcException me) {
            if (me.isBiz()) {
                result = new RpcResult(me.getCause());
            } else {
                throw new RpcException(me.getCode(), getMockExceptionMessage(e, me), me.getCause());
            }
        } catch (Throwable me) {
            throw new RpcException(getMockExceptionMessage(e, me), me.getCause());
        }
        return result;
    }
//REFER2.2.4.2 FailoverCluster.join--创建FailoverClusterInvoker
public class FailoverCluster implements Cluster {

    public final static String NAME = "failover";

    @Override
    public <T> Invoker<T> join(Directory<T> directory) throws RpcException {
      //创建包含失败重试逻辑的invoker
        return new FailoverClusterInvoker<T>(directory);
    }
REFER2.2.5 ProviderConsumerRegTable.registerConsumer(invoker, url, subscribeUrl, directory)

image-20230101171631893

然后,将consumer和provider注册存入ProviderConsumerRegTable,方法参数此时如下:

image-20230101172203659

 public static void registerConsumer(Invoker invoker, URL registryUrl, URL consumerUrl, RegistryDirectory registryDirectory) {
        ConsumerInvokerWrapper wrapperInvoker = new ConsumerInvokerWrapper(invoker, registryUrl, consumerUrl, registryDirectory);
  			 //com.alibaba.dubbo.demo.DemoService
        String serviceUniqueName = consumerUrl.getServiceKey();
        Set<ConsumerInvokerWrapper> invokers = consumerInvokers.get(serviceUniqueName);
        if (invokers == null) {
            consumerInvokers.putIfAbsent(serviceUniqueName, new ConcurrentHashSet<ConsumerInvokerWrapper>());
            invokers = consumerInvokers.get(serviceUniqueName);
        }
        invokers.add(wrapperInvoker);
    }

TAG1.3 proxyFactory.getProxy(invoker)

public class ProxyFactory$Adaptive implements com.alibaba.dubbo.rpc.ProxyFactory {
    public java.lang.Object getProxy(com.alibaba.dubbo.rpc.Invoker arg0) throws com.alibaba.dubbo.rpc.RpcException {
        if (arg0 == null) throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument == null");
        if (arg0.getUrl() == null) throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument getUrl() == null");com.alibaba.dubbo.common.URL url = arg0.getUrl();
        String extName = url.getParameter("proxy", "javassist");//javassist
        if(extName == null) throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.ProxyFactory) name from url(" + url.toString() + ") use keys([proxy])");
        com.alibaba.dubbo.rpc.ProxyFactory extension = (com.alibaba.dubbo.rpc.ProxyFactory)ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.ProxyFactory.class).getExtension(extName);
//TAG1.3.1 StubProxyFactoryWrapper.getProxy
        return extension.getProxy(arg0);
    }

image-20230101174133206

获取stub包裹的ProxyFactory。

TAG1.3.1 StubProxyFactoryWrapper.getProxy
StubProxyFactoryWrapper
   public <T> T getProxy(Invoker<T> invoker) throws RpcException {
//TAG1.3.1.1 JavassistProxyFactory.getProxy 创建代理对象
        T proxy = proxyFactory.getProxy(invoker);
        if (GenericService.class != invoker.getInterface()) {
            String stub = invoker.getUrl().getParameter(Constants.STUB_KEY, invoker.getUrl().getParameter(Constants.LOCAL_KEY));
/**………………………………………………………………………………………………………………处理stub………………………………………………………………………………………………………… */
            if (ConfigUtils.isNotEmpty(stub)) {
                Class<?> serviceType = invoker.getInterface();
                if (ConfigUtils.isDefault(stub)) {
                    if (invoker.getUrl().hasParameter(Constants.STUB_KEY)) {
                        stub = serviceType.getName() + "Stub";
                    } else {
                        stub = serviceType.getName() + "Local";
                    }
                }
                try {
                    Class<?> stubClass = ReflectUtils.forName(stub);
                    if (!serviceType.isAssignableFrom(stubClass)) {
                        throw new IllegalStateException("The stub implementation class " + stubClass.getName() + " not implement interface " + serviceType.getName());
                    }
                    try {
                        Constructor<?> constructor = ReflectUtils.findConstructor(stubClass, serviceType);
                        proxy = (T) constructor.newInstance(new Object[]{proxy});
                        //export stub service
                        URL url = invoker.getUrl();
                        if (url.getParameter(Constants.STUB_EVENT_KEY, Constants.DEFAULT_STUB_EVENT)) {
                            url = url.addParameter(Constants.STUB_EVENT_METHODS_KEY, StringUtils.join(Wrapper.getWrapper(proxy.getClass()).getDeclaredMethodNames(), ","));
                            url = url.addParameter(Constants.IS_SERVER_KEY, Boolean.FALSE.toString());
                            try {
                                export(proxy, (Class) invoker.getInterface(), url);
                            } catch (Exception e) {
                                LOGGER.error("export a stub service error.", e);
                            }
                        }
                    } catch (NoSuchMethodException e) {
                        throw new IllegalStateException("No such constructor \"public " + stubClass.getSimpleName() + "(" + serviceType.getName() + ")\" in stub implementation class " + stubClass.getName(), e);
                    }
                } catch (Throwable t) {
                    LOGGER.error("Failed to create stub implementation class " + stub + " in consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion() + ", cause: " + t.getMessage(), t);
                    // ignore
                }
            }
        }
        return proxy;
    }
TAG1.3.1.1 JavassistProxyFactory.getProxy
public abstract class AbstractProxyFactory implements ProxyFactory {

    @Override
    public <T> T getProxy(Invoker<T> invoker) throws RpcException {
        return getProxy(invoker, false);
    }
  
      public <T> T getProxy(Invoker<T> invoker, boolean generic) throws RpcException {
        Class<?>[] interfaces = null;
        //invoker.getUrl()获取url为zookeeper://127.0.0.1:2181,即注册中心url
        //这里获取"interfaces"参数,是获取多个接口
        String config = invoker.getUrl().getParameter("interfaces"); //null
/**……………………………………………………处理多个interfaces情况………………………………………………………………………… */
        if (config != null && config.length() > 0) {
            String[] types = Constants.COMMA_SPLIT_PATTERN.split(config);
            if (types != null && types.length > 0) {
              //将invoker.getInterface、EchoService加入interfaces集合中
                interfaces = new Class<?>[types.length + 2];
                interfaces[0] = invoker.getInterface();
                interfaces[1] = EchoService.class;
                for (int i = 0; i < types.length; i++) {
                    interfaces[i + 1] = ReflectUtils.forName(types[i]);
                }
            }
        }
        if (interfaces == null) {
          //创建两个Class对象--DemoService、
            interfaces = new Class<?>[]{invoker.getInterface(), EchoService.class};
        }
				//generic=false
        if (!invoker.getInterface().equals(GenericService.class) && generic) {
            int len = interfaces.length;
            Class<?>[] temp = interfaces;
            interfaces = new Class<?>[len + 1];
            System.arraycopy(temp, 0, interfaces, 0, len);
            interfaces[len] = GenericService.class;
        }
//交给子类实现
        return getProxy(invoker, interfaces);
    }
public class JavassistProxyFactory extends AbstractProxyFactory {

    @Override
    @SuppressWarnings("unchecked")
    public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
      //调用javassist框架,创建代理方式创建代理对象
        return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
    }

使用javassist的动态代理,创建实例对象。传入调用处理器,所有的方法调用,会交给此调用方法调用管理器,拦截执行

package com.alibaba.dubbo.rpc.proxy;
//dubbo实现的InvocationHandler
public class InvokerInvocationHandler implements InvocationHandler {

    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();//方法参数类型
      	//声明method的类是Object.class
        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]);
        }
//代理对象的方法调用,会转交给invoker.invoke执行
        return invoker.invoke(new RpcInvocation(method, args)).recreate();
    }

}

image-20230101181317347

最后,在referenceConfig中创建的ref代理对象如下:

image-20230101190102857

image-20230101193827590

DubboInvoker具有通信功能,其内部初始化并开启Netty服务的NettyClient

image-20230101194444994

posted @ 2023-03-13 14:47  LeasonXue  阅读(29)  评论(0编辑  收藏  举报