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