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