Dubbo源碼閱讀之 客戶端遠程調用

【 DubboProtocolTest.java ====>> 客戶端 ====>> DemoService.class的代理類 】
1. 構造函數:ccp.addConstructor(Modifier.PUBLIC, new Class<?>[]{ InvocationHandler.class }, new Class<?>[0], "handler=$1;");
2. 初始化:
public Object newInstance(java.lang.reflect.InvocationHandler h){ 
return new com.alibaba.dubbo.common.bytecode.proxy0($1); 
}
3. 方法 sayHello
public void sayHello(java.lang.String arg0){
Object[] args = new Object[1]; 
args[0] = ($w)$1; 
Object ret = handler.invoke(this, methods[12], args);
}


【 DubboProtocolTest.java ====>> 客戶端 ====>> DubboInvoker.java 】
1. 字段
private final ExchangeClient[]      clients;
private final Set<Invoker<?>> invokers;
private final Class<T>   type;
private final URL        url;
2. 方法
Class<T> getInterface();
                        ======>>> 獲取接口。
    Result invoke(Invocation invocation) throws RpcException;
                        ======>>> 調用目標方法。




【 DubboProtocolTest.java ====>> 客戶端 ====>> RpcInvocation.java 】
1. 字段
private String               methodName;
    private Class<?>[]           parameterTypes;
    private Object[]             arguments;
    private Map<String, String>  attachments;
    private transient Invoker<?> invoker;


2. 方法
String getMethodName();
Class<?>[] getParameterTypes();
Object[] getArguments();
Map<String, String> getAttachments();
String getAttachment(String key);
String getAttachment(String key, String defaultValue);
    Invoker<?> getInvoker();


【 DubboProtocolTest.java ====>> RPC ====>> 遠程調用 】
1. 初始化 RpcInvocation
                        ======>>> 方法名稱,方法參數。
2. 初始化 Request
                        ======>>> Request req = new Request();
                        ======>>> req.setVersion("2.0.0");
                        ======>>> req.setTwoWay(true);
                        ======>>> req.setData(request);
3. NettyClient 中直接發送出去。
4. NettyServer 接收到消息,
5. 判斷消息是否是Request,if (message instanceof Request){}
6. 判斷是否是Event,if (request.isEvent())
7. 是否是TwoWay,if (request.isTwoWay())
8. 判斷請求對象是否是壞的,if (req.isBroken())
9. 根據key來尋找目標DubboExporter,key的生成方式:key = 組名 + 服務名 + 服務版本 + 端口
    public static String serviceKey(int port, String serviceName, String serviceVersion, String serviceGroup) {
        StringBuilder buf = new StringBuilder();
        if (serviceGroup != null && serviceGroup.length() > 0) {
            buf.append(serviceGroup);
            buf.append("/");
        }
        buf.append(serviceName);
        if (serviceVersion != null && serviceVersion.length() > 0 && !"0.0.0".equals(serviceVersion)) {
            buf.append(":");
            buf.append(serviceVersion);
        }
        buf.append(":");
        buf.append(port);
        return buf.toString();
    }
10. 調用目標方法,返回結果,invoker.invoke(inv);
11. 封裝響應對象,如果調用成功,響應對象爲Response res = new Response(req.getId(), req.getVersion());res.setStatus(Response.OK);res.setResult(result);
12. 返回響應對象,發送給NettyClient,channel.send(response);
13. NettyClient接收到響應消息,根絕請求ID,回去Future,DefaultFuture future = FUTURES.remove(response.getId());
14. 往future中寫數據,
private void doReceived(Response res) {
        lock.lock();
        try {
            response = res;
            if (done != null) {
                done.signal();
            }
        } finally {
            lock.unlock();
        }
        if (callback != null) {
            invokeCallback(callback);
        }
    }
15,主線程獲取dubbo調用返回結果,
public Object get(int timeout) throws RemotingException {
        if (timeout <= 0) {
            timeout = Constants.DEFAULT_TIMEOUT;
        }
        if (! isDone()) {
            long start = System.currentTimeMillis();
            lock.lock();
            try {
                while (! isDone()) {
                    done.await(timeout, TimeUnit.MILLISECONDS);
                    if (isDone() || System.currentTimeMillis() - start > timeout) {
                        break;
                    }
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } finally {
                lock.unlock();
            }
            if (! isDone()) {
                throw new TimeoutException(sent > 0, channel, getTimeoutMessage(false));
            }
        }
        return returnFromResponse();
    }

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