今天學習的是rpc包中的thrift協議的使用過程,以下是簡單的調用步驟,在這裏記錄一下並做了點簡單的說明。
1、首先初始化Protocol類
Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getExtension( ThriftProtocol.NAME );
2、以服務的接口類和URL爲參數,調用protocol的refer()方法,返回一個具體協議的Invoker對象,此處以thrift舉例,故返回ThriftInvoker對象實例;
public <T> Invoker<T> refer( Class<T> type, URL url ) throws RpcException {
ThriftInvoker<T> invoker = new ThriftInvoker<T>(type, url, getClients(url), invokers);
invokers.add(invoker);
return invoker;
}
3、RpcInvocation類繼承自Invocation類,主要是對回調方法的一些方法名、參數及類型等一些參數的設置,然後作爲以上invoker對象調用invoke方法時的參數,來返回結果。
RpcInvocation invocation = new RpcInvocation();
invocation.setMethodName( "echoString" );
invocation.setParameterTypes( new Class<?>[]{ String.class } );
String arg = "Hello, World!";
invocation.setArguments( new Object[] { arg } );
Result result = invoker.invoke( invocation );
4、invoke方法是在AbstractInvoker抽象類中進行了實現,主要還是對RpcInvocation的一些參數進行設置,具體的回調操作doInvoke(invocation)由具體協議實現
public Result invoke(Invocation inv) throws RpcException {
if(destroyed) {
throw new RpcException("Rpc invoker for service " + this + " on consumer " + NetUtils.getLocalHost()
+ " use dubbo version " + Version.getVersion()
+ " is DESTROYED, can not be invoked any more!");
}
RpcInvocation invocation = (RpcInvocation) inv;
invocation.setInvoker(this);
if (attachment != null && attachment.size() > 0) {
invocation.addAttachmentsIfAbsent(attachment);
}
Map<String, String> context = RpcContext.getContext().getAttachments();
if (context != null) {
invocation.addAttachmentsIfAbsent(context);
}
if (getUrl().getMethodParameter(invocation.getMethodName(), Constants.ASYNC_KEY, false)){
invocation.setAttachment(Constants.ASYNC_KEY, Boolean.TRUE.toString());
}
RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);
try {
<span style="background-color: rgb(255, 255, 102);">return doInvoke(invocation);//由具體協議實現</span>
} catch (InvocationTargetException e) { // biz exception
Throwable te = e.getTargetException();
if (te == null) {
return new RpcResult(e);
} else {
if (te instanceof RpcException) {
((RpcException) te).setCode(RpcException.BIZ_EXCEPTION);
}
return new RpcResult(te);
}
} catch (RpcException e) {
if (e.isBiz()) {
return new RpcResult(e);
} else {
throw e;
}
} catch (Throwable e) {
return new RpcResult(e);
}
}
5、在doInvoker()中主要是隨機選擇一個ExchangeClient對象進行異步回調,得到相應的結果。
protected Result doInvoke( Invocation invocation ) throws Throwable {
RpcInvocation inv = (RpcInvocation) invocation;
final String methodName;
methodName = invocation.getMethodName();
inv.setAttachment( Constants.PATH_KEY, getUrl().getPath() );
// for thrift codec
inv.setAttachment( ThriftCodec.PARAMETER_CLASS_NAME_GENERATOR, getUrl().getParameter(
ThriftCodec.PARAMETER_CLASS_NAME_GENERATOR, DubboClassNameGenerator.NAME ) );
ExchangeClient currentClient;
if (clients.length == 1) {
currentClient = clients[0];
} else {
currentClient = clients[index.getAndIncrement() % clients.length];//隨機選擇一個Client
}
try {
int timeout = getUrl().getMethodParameter(
methodName, Constants.TIMEOUT_KEY,Constants.DEFAULT_TIMEOUT);
RpcContext.getContext().setFuture(null);
return (Result) currentClient.request(inv, timeout).get();//進行方法異步回調
} catch (TimeoutException e) {
throw new RpcException(RpcException.TIMEOUT_EXCEPTION, e.getMessage(), e);
} catch (RemotingException e) {
throw new RpcException(RpcException.NETWORK_EXCEPTION, e.getMessage(), e);
}
}