【 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();
}
Dubbo源碼閱讀之 客戶端遠程調用
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.