Dubbo服务调用过程

在这里插入图片描述
引用

在这里插入图片描述

refer

根据远端服务的接口serviceType和服务地址信息url创建RPC代理

public <T> Invoker<T> refer(Class<T> serviceType, URL url) throws RpcException {
    optimizeSerialization(url);
    // create rpc invoker.
    DubboInvoker<T> invoker = 
        new DubboInvoker<T>(serviceType, url, getClients(url), invokers);
    invokers.add(invoker);
    return invoker;
}

创建客户端

通过一顿设计模式的操作,由HeaderExchanger调用NettyTransporter创建一个NettyClient

/**
 * 通过netty创建url连接的客户端
 * @see NettyClient#open()
 */
client = Exchangers.connect(url, requestHandler);
/**
 * @see AbstractClient#AbstractClient(URL, ChannelHandler) AbstractClient的构造方法中调用doOpen
 */
@Override
protected void doOpen() throws Throwable {
    NettyHelper.setNettyLoggerFactory();
    bootstrap = new ClientBootstrap(channelFactory);
    // config
    // @see org.jboss.netty.channel.socket.SocketChannelConfig
    bootstrap.setOption("keepAlive", true);
    bootstrap.setOption("tcpNoDelay", true);
    bootstrap.setOption("connectTimeoutMillis", getConnectTimeout());
    // nettyClient(继承链中的AbstractPeer)作为requestHandler的代理类 自己作为ChannelHandler
    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;
        }
    });
}

Invoker

org.apache.dubbo.rpc.protocol.AbstractInvoker的子类 (默认实现Dubbo)

invoker保存了这个rpc调用所需信息(url、接口类)和网络资源(NettyClient)

一个invoker对应多个client,表示一个服务有多个服务提供地址

private final ExchangeClient[] clients;

// balabala
// 轮询策略
if (clients.length == 1) {
    currentClient = clients[0];
} else {
    currentClient = clients[index.getAndIncrement() % clients.length];
}

doInvoke

doInvoke方法不同协议的远程调用实现,默认实现为dubbo

由Proxy代理实例调用doInvoke,与服务提供方进行数据交互

/**
 * 基于dubbo协议的远程调用实现
 * @param invocation 远程调用信息封装
 */
@Override
protected Result doInvoke(final Invocation invocation) throws Throwable {
    RpcInvocation inv = (RpcInvocation) invocation;
    final String methodName = RpcUtils.getMethodName(invocation);
    inv.setAttachment(Constants.PATH_KEY, getUrl().getPath());
    inv.setAttachment(Constants.VERSION_KEY, version);

    ExchangeClient currentClient;
    if (clients.length == 1) {
        currentClient = clients[0];
    } else {
        currentClient = clients[index.getAndIncrement() % clients.length];
    }
    try {
        boolean isAsync = RpcUtils.isAsync(getUrl(), invocation);
        boolean isAsyncFuture = RpcUtils.isGeneratedFuture(inv) || RpcUtils.isFutureReturnType(inv);
        boolean isOneway = RpcUtils.isOneway(getUrl(), invocation);
        int timeout = getUrl().getMethodParameter(methodName, Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT);
        if (isOneway) {
            boolean isSent = getUrl().getMethodParameter(methodName, Constants.SENT_KEY, false);
            // 阻塞请求
            currentClient.send(inv, isSent);
            RpcContext.getContext().setFuture(null);
            return new RpcResult();
        } else if (isAsync) {
            // 异步请求
            ResponseFuture future = currentClient.request(inv, timeout);
            // For compatibility
            FutureAdapter<Object> futureAdapter = new FutureAdapter<>(future);
            RpcContext.getContext().setFuture(futureAdapter);

            Result result;
            if (isAsyncFuture) {
                // register resultCallback
                result = 
                    new AsyncRpcResult(futureAdapter, futureAdapter.getResultFuture(), false);
            } else {
                result = 
                    new SimpleAsyncRpcResult(futureAdapter, futureAdapter.getResultFuture(), false);
            }
            return result;
        } else {
            RpcContext.getContext().setFuture(null);
            return (Result) currentClient.request(inv, timeout).get();
        }
    } catch (TimeoutException e) {
        throw new RpcException(RpcException.TIMEOUT_EXCEPTION, "Invoke remote method timeout. method: " + invocation.getMethodName() + ", provider: " + getUrl() + ", cause: " + e.getMessage(), e);
    } catch (RemotingException e) {
        throw new RpcException(RpcException.NETWORK_EXCEPTION, "Failed to invoke remote method: " + invocation.getMethodName() + ", provider: " + getUrl() + ", cause: " + e.getMessage(), e);
    }
}

Proxy.getProxy.newInstance

根据invoker中的信息,创建RPC的本地代理实例(instance),供业务层调用(作为Component存入Spring容器中)

获取proxy

Proxy.getProxy 静态方法

根据服务的接口类生成代理类的class对象 extends Proxy implements serviceInterface

<T> T getProxy(Invoker<T> invoker) throws RpcException;

Proxy.getProxy(ClassLoader cl, Class<?>... ics) javassist实现

构造函数

getProxy为生成的所有代理类添加一个InvocationHandler的私有变量和构造函数

ccp.addField("private " + InvocationHandler.class.getName() + " handler;");
ccp.addConstructor(Modifier.PUBLIC, new Class<?>[]{InvocationHandler.class}, new Class<?>[0], "handler=$1;");

后面newInstance方法中,就是调用这个构造方法,new出来的代理对象

方法列表

javassist动态生成的代理的方法

  • 服务接口的方法
  • newInstance(handler)

自动生成的实现代码示例

public String interfaceMethodName($1){
    Object[] args = new Object[1]; 
    args[0] = ($w)$1; 
    Object ret = handler.invoke(this, methods[2], args); 
    return (java.lang.String)ret;
}

获取代理实例

proxy.newInstance(handler) 实例方法

在创建实例时将上面创建负责发起远端请求的invoker封装成handler注入到代理实例中;在调用实例方法时,会将调用方法转成invocation,将rpc调用的结果Result

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章