dubbo的url里面帶的callback是怎么用的?


在url里面指定某個參數方法的第幾個參數是一個callback,也就是說這個實參是一個callback,雖然消費者把這個callback實例傳給了提供者,但是提供者實際本地沒有這個callback實例,提供者只能繼續遠程調用消費者這個callback拿到結果。

 

比如消費者和提供者都在url里面指定 xxx.0.callback=true,表示xxx這個method的第0個參數是一個callback。

 

提供者有這樣一個接口服務:

public void xxx(IDemoCallback callback, String arg1, int runs, int sleep);

提供者具體實現:

 

public void xxx(final IDemoCallback callback, String arg1, final int runs, final int sleep) {
callback.yyy("Sync callback msg .This is callback data. arg1:" + arg1);
System.out.println("xxx invoke complete");
}

對於提供者來說,這個callback是消費傳過來的一個實例,本地沒有,那么在調用的時候如果執行到callback只能遠程調用消費者這個callback實例拿到結果再繼續運行

System.out.println("xxx invoke complete");

消費者調用了方式:

demoProxy.xxx(new IDemoCallback() {
public String yyy(String msg) {
System.out.println("Recived callback: " + msg);
count.incrementAndGet();
return "ok";
}
}, "other custom args", 10, 100);


下面解釋下dubbo如何做的。對於一個rpc調用是這么序列化的:

method-name按照striing序列化

parameter-type按照類型的描述符的string進行序列化

對於arguments,如果不是callback,也就是沒有在url指定 xxx.0.callback=true這種的話,那么直接在hessian序列化

 

 

public static Object encodeInvocationArgument(Channel channel, RpcInvocation inv, int paraIndex) throws IOException {
// get URL directly
URL url = inv.getInvoker() == null ? null : inv.getInvoker().getUrl();
byte callbackstatus = isCallBack(url, inv.getMethodName(), paraIndex);
Object[] args = inv.getArguments();
Class<?>[] pts = inv.getParameterTypes();
switch (callbackstatus) {
case CallbackServiceCodec.CALLBACK_NONE:
return args[paraIndex];
case CallbackServiceCodec.CALLBACK_CREATE:
inv.setAttachment(INV_ATT_CALLBACK_KEY + paraIndex, exportOrunexportCallbackService(channel, url, pts[paraIndex], args[paraIndex], true));
return null;
case CallbackServiceCodec.CALLBACK_DESTROY:
inv.setAttachment(INV_ATT_CALLBACK_KEY + paraIndex, exportOrunexportCallbackService(channel, url, pts[paraIndex], args[paraIndex], false));
return null;
default:
return args[paraIndex];
}
}

那么如果是一個callback的話,return null沒有在argument進行序列化,而是把一個callback實例通過exportOrunexportCallbackService放到attachment里面,具體這個exportOrunexportCallbackService干了啥呢?具體比較復雜,總結來說就是構造了一個新的dubboinvoer,這個invoker的interface就是這個callback的interface+hashcode(加hashcode考慮有多個interface的callback,他們在不同的方法上),他提供的方法就是這個callback要做的方法。

也就是說消費者在把callback序列化的時候,實際上構造了一個dubboinvoker,等待提供者來調用。

提供者在接收到消息的時候,對method-name、parameter-type進行反序列化,並且通過url知道哪些參數是一個callback,接着以這個遠端的channel(在netty回調的時候decode方法可以輕松拿到這個channel)構造了一個referinvoker

這個referinvoker就是對消費者callback的一個抽象,同樣的這個invoker的interface就是這個callback的interface+hashcode(加hashcode考慮有多個interface的callback,他們在不同的方法上),他提供的方法就是這個callback要做的方法。

也就是說提供者反序列化的時候,對這個callback實現了一個referinvoker,等到真正要調用這個callback的時候,雖然是本地執行,實際上是遠程調用到消費者,而不是在本地執行callback。

 

 

 
       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM