大纲
1.对动态代理接口的方法进行调用时的入口
2.动态代理基于Invoker执行RPC调用
3.服务发现获取目标服务实例集群Invokers
4.DynamicDirectory进行服务发现的流程
5.构造DubboInvoker并建立网络连接的过程
6.LoadBalance的负载均衡机制
7.Dubbo进行RPC调用时的异步执行过程
8.Dubbo进行RPC调用后会如何等待响应
9.NettyServer会如何调用本地代码
10.Dubbo的分层架构原理
1.对动态代理接口的方法进行调用时的入口
当执行完Reference的get()方法生成动态代理的接口后,就可以调用接口的方法了。
当动态代理的接口方法被调用时,会进入InvokerInvocationHandler的invoke()方法中。
java
public class Application {
public static void main(String[] args) throws Exception {
//Reference和ReferenceConfig是什么
//Reference是一个引用,是对Provider端的一个服务实例的引用
//ReferenceConfig这个服务实例的引用的一些配置
//通过泛型传递了这个服务实例对外暴露的接口
ReferenceConfig<DemoService> reference = new ReferenceConfig<>();
//设置应用名称
reference.setApplication(new ApplicationConfig("dubbo-demo-api-consumer"));
//设置注册中心的地址,默认是ZooKeeper
reference.setRegistry(new RegistryConfig("zookeeper://127.0.0.1:2181"));
//设置元数据上报地址
reference.setMetadataReportConfig(new MetadataReportConfig("zookeeper://127.0.0.1:2181"));
//设置要调用的服务的接口
reference.setInterface(DemoService.class);
//直接通过ReferenceConfig的get()方法来拿到一个DemoService接口
//它是一个动态代理接口,只要被调用,便会通过底层调用Provider服务实例的对应接口
DemoService service = reference.get();
//下面调用动态代理的接口
//会进入InvokerInvocationHandler的invoke()方法中
String message = service.sayHello("dubbo");
System.out.println(message);
Thread.sleep(10000000L);
}
}
//实现了JDK反射机制里的InvocationHandler接口
public class InvokerInvocationHandler implements InvocationHandler {
...
public InvokerInvocationHandler(Invoker<?> handler) {
this.invoker = handler;
URL url = invoker.getUrl();
this.protocolServiceKey = url.getProtocolServiceKey();
this.serviceModel = url.getServiceModel();
}
//通过这个代理对象可以拿到这个代理对象的接口
//通过接口就可以定位到目标服务实例发布的服务接口,从而针对目标服务实例进行调用
//拿到了调用目标服务实例的方法、传递进去的参数等信息,就可以进行完整的RPC调用
//动态代理就是针对接口动态去生成该接口的实现类并进行调用
//比如针对DemoService这个接口去生成一个实现类
//由于这个实现类是动态生成的,那么它如何知道会有调用方去调用它的方法,以及又如何去执行?
//为此,动态代理底层都会封装InvocationHandler
//封装完后对动态代理所有方法的调用,都会跑到InvocationHandler这里来
//这样,InvocationHandler的invoke方法就可以拿到:
//Proxy动态代理对象、需要调用对象的哪个方法Method、以及被调用方法会传入的参数args
//此时,对动态代理不同方法的调用以及具体方法被调用后会如何处理
//都可以由如下invoke()方法发起远程调用由服务提供者来决定
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//对于Object中定义的方法,直接调用Invoker对象的相应方法即可
if (method.getDeclaringClass() == Object.class) {
return method.invoke(invoker, args);
}
String methodName = method.getName();
Class<?>[] parameterTypes = method.getParameterTypes();
if (parameterTypes.length == 0) {
if ("toString".equals(methodName)) {
//对toString()方法进行特殊处理
return invoker.toString();
} else if ("$destroy".equals(methodName)) {
//对$destroy等方法的特殊处理
invoker.destroy();
return null;
} else if ("hashCode".equals(methodName)) {
//对hashCode()方法进行特殊处理
return invoker.hashCode();
}
} else if (parameterTypes.length == 1 && "equals".equals(methodName)) {
return invoker.equals(args[0]);
}
//创建RpcInvocation对象,后面会作为远程RPC调用的参数
//Consumer端进行RPC调用时,必须要封装一个RpcInvocation
//这个RpcInvocation会传递到Provider端
//Provider端拿到请求数据后,也会封装一个RpcInvocation
RpcInvocation rpcInvocation = new RpcInvocation(serviceModel, method.getName(), invoker.getInterface().getName(), protocolServiceKey, method.getParameterTypes(), args);
if (serviceModel instanceof ConsumerModel) {
rpcInvocation.put(Constants.CONSUMER_MODEL, serviceModel);
rpcInvocation.put(Constants.METHOD_MODEL, ((ConsumerModel) serviceModel).getMethodModel(method));
}
//调用invoke()方法发起远程调用
//拿到AsyncRpcResult之后,调用recreate()方法获取响应结果(或是Future)
//下面的invoker其实就是装饰了MockClusterInvoker的MigrationInvoker
return InvocationUtil.invoke(invoker, rpcInvocation);
}
}
public class InvocationUtil {
public static Object invoke(Invoker<?> invoker, RpcInvocation rpcInvocation) throws Throwable {
...
//为什么要进行recreate?
//recreate是为了对拿到的结果进行一个拷贝,将拷贝出来的结果对象返回给业务方去使用
//这样Dubbo框架内部自己可以持有一个结果对象,避免了和业务方共享持有和访问,而产生相互的影响
return invoker.invoke(rpcInvocation).recreate();
}
}
2.动态代理基于Invoker执行RPC调用
InvokerInvocationHandler的invoke()方法会调用InvocationUtil的invoke()方法,而后者又会返回"invoker.invoke(rpcInvocation).recreate()"的结果。其中,这个invoker是装饰了MockClusterInvoker的MigrationInvoker。所以,调用MigrationInvoker的invoke()方法时,会调用MockClusterInvoker的invoke()方法。
最终会调用AbstractClusterInvoker的invoke()方法,该方法会根据invocation信息列出所有的Invoker,也就是通过DynamicDirectory的list()方法进行服务发现,从而列出有哪些服务实例和有哪些Invoker,其中一个服务实例会对应一个Invoker。
arduino
//-> InvokerInvocationHandler.invoke()
//-> InvocationUtil.invoke()
// invoker.invoke(rpcInvocation).recreate()
//-> MigrationInvoker.invoke()
//-> MockClusterInvoker.invoke()
//-> AbstractCluster.ClusterFilterInvoker.invoke()
//-> FilterChainBuilder.CallbackRegistrationInvoker.invoke()
//-> FilterChainBuilder.CopyOfFilterChainNode.invoke()
//-> ConsumerContextFilter.invoke()
//-> FilterChainBuilder.CopyOfFilterChainNode.invoke()
//-> FutureFilter.invoke()
//-> FilterChainBuilder.CopyOfFilterChainNode.invoke()
//-> MonitorFilter.invoke()
//-> FilterChainBuilder.CopyOfFilterChainNode.invoke()
//-> RouterSnapshotFilter.invoke()
//-> AbstractClusterInvoker.invoke()
//-> AbstractClusterInvoker.list()
//-> DynamicDirectory.list()
//-> FailoverClusterInvoker.doInvoke()
java
public class InvocationUtil {
public static Object invoke(Invoker<?> invoker, RpcInvocation rpcInvocation) throws Throwable {
...
//调用invoke()方法发起远程调用
//拿到AsyncRpcResult之后,调用recreate()方法获取响应结果(或是Future)
//下面的invoker其实就是装饰了MockClusterInvoker的MigrationInvoker
return invoker.invoke(rpcInvocation).recreate();
}
}
public class MigrationInvoker<T> implements MigrationClusterInvoker<T> {
//服务引用时,它是一个MockClusterInvoker
private volatile ClusterInvoker<T> invoker;
//这是一个名为serviceDiscoveryInvoker的ClusterInvoker实现类的实例,也是一个MockClusterInvoker
private volatile ClusterInvoker<T> serviceDiscoveryInvoker;
//服务引用时,它是一个MockClusterInvoker
private volatile ClusterInvoker<T> currentAvailableInvoker;
...
//真正在执行Invoker调用时,可以在这里看到MigrationInvoker里的逻辑
//为什么会叫MigrationInvoker?因为MigrationInvoker有两个Invoker:一个是invoker,一个是serviceDiscoveryInvoker
//执行这里的invoke()方法时会根据不同的条件去切换这两个invoker,将它们之一赋值给真正负责执行invoke()方法的currentAvailableInvoker
//也就是有一个针对currentAvailableInvoker进行切换的过程(根据不同的条件来切换是invoker还是serviceDiscoveryInvoker),所以migration就是从这里来的
@Override
public Result invoke(Invocation invocation) throws RpcException {
...
//check if invoker available for each time
return decideInvoker().invoke(invocation);
}
private ClusterInvoker<T> decideInvoker() {
if (currentAvailableInvoker == serviceDiscoveryInvoker) {
if (checkInvokerAvailable(serviceDiscoveryInvoker)) {
return serviceDiscoveryInvoker;
}
return invoker;
} else {
return currentAvailableInvoker;
}
}
public boolean checkInvokerAvailable(ClusterInvoker<T> invoker) {
//其实就是调用MockClusterInvoker的isAvailable()来检查是否可用
return invoker != null && !invoker.isDestroyed() && invoker.isAvailable();
}
...
}
public class MockClusterInvoker<T> implements ClusterInvoker<T> {
private final Directory<T> directory;
private final Invoker<T> invoker;
public MockClusterInvoker(Directory<T> directory, Invoker<T> invoker) {
//传入的directory为DynamicDirectory
//当初始化MigrationInvoker.invoker时,传入的directory为RegistryDirectory
//当初始化MigrationInvoker.serviceDiscoveryInvoker时,传入的directory为ServiceDiscoveryRegistryDirectory
//不管是RegistryDirectory,还是ServiceDiscoveryRegistryDirectory,其实都是DynamicDirectory
this.directory = directory;
///传入的invoker为AbstractCluster的内部类ClusterFilterInvoker
//其filterInvoker属性的originalInvoker属性便为封装了DynamicDirectory的FailoverClusterInvoker
this.invoker = invoker;
}
@Override
public boolean isAvailable() {
return directory.isAvailable();
}
@Override
public Result invoke(Invocation invocation) throws RpcException {
...
//这里会直接发起正常的调用
//每一层Invoker都会去负责自己的事情,对Invoker的调用使用了严格的责任链模式,运用了责任链模式的思想
//A Invoker->B Invoker->C Invoker->D Invoker
//在发起RPC调用时,由于会涉及到很多的机制,比如降级调用机制(mock),集群容错机制,负载均衡机制等
//此时如果只有一个Invoker,那么它里面的代码就会很多很复杂,所以才用上了责任链模式
//下面会调用AbstractCluster内部类ClusterFilterInvoker的invoke()方法,进行正常的RPC调用
result = this.invoker.invoke(invocation);
...
return result;
}
...
}
public abstract class AbstractCluster implements Cluster {
...
static class ClusterFilterInvoker<T> extends AbstractClusterInvoker<T> {
...
@Override
public Result invoke(Invocation invocation) throws RpcException {
//下面会调用FilterChainBuilder的内部类CallbackRegistrationInvoker的invoke()方法
return filterInvoker.invoke(invocation);
}
...
}
...
}
@SPI(value = "default", scope = APPLICATION)
public interface FilterChainBuilder {
...
class CallbackRegistrationInvoker<T, FILTER extends BaseFilter> implements Invoker<T> {
final Invoker<T> filterInvoker;
final List<FILTER> filters;
public CallbackRegistrationInvoker(Invoker<T> filterInvoker, List<FILTER> filters) {
//这是一个CopyOfFilterChainNode
this.filterInvoker = filterInvoker;
//[ConsumerContextFilter, FutureFilter, MonitorFilter, RouterSnapshotFilter]
this.filters = filters;
}
public Result invoke(Invocation invocation) throws RpcException {
//下面首先会调用FilterChainBuilder$CopyOfFilterChainNode.invoke()
Result asyncResult = filterInvoker.invoke(invocation);
...
}
...
}
class CopyOfFilterChainNode<T, TYPE extends Invoker<T>, FILTER extends BaseFilter> implements Invoker<T> {
...
@Override
public Result invoke(Invocation invocation) throws RpcException {
Result asyncResult;
try {
InvocationProfilerUtils.enterDetailProfiler(invocation, () -> "Filter " + filter.getClass().getName() + " invoke.");
//比如Consumer端处理时下面会调用ConsumerContextFilter的invoke()方法
//Provider端处理时下面会最终调用AbstractProxyInvoker.invoke()方法
asyncResult = filter.invoke(nextNode, invocation);
} catch (Exception e) {
...
}
...
}
...
}
...
}
@Activate(group = CONSUMER, order = Integer.MIN_VALUE)
public class ConsumerContextFilter implements ClusterFilter, ClusterFilter.Listener {
...
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
...
//下面又会调用FilterChainBuilder的内部类CopyOfFilterChainNode的invoke()方法
return invoker.invoke(invocation);
}
...
}
@Activate(group = CommonConstants.CONSUMER)
public class FutureFilter implements ClusterFilter, ClusterFilter.Listener {
...
@Override
public Result invoke(final Invoker<?> invoker, final Invocation invocation) throws RpcException {
//触发invoker调用的回调
fireInvokeCallback(invoker, invocation);
//下面又会调用FilterChainBuilder的内部类CopyOfFilterChainNode的invoke()方法
return invoker.invoke(invocation);
}
...
}
@Activate(group = {PROVIDER})
public class MonitorFilter implements Filter, Filter.Listener {
...
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
if (invoker.getUrl().hasAttribute(MONITOR_KEY)) {
invocation.put(MONITOR_FILTER_START_TIME, System.currentTimeMillis());
invocation.put(MONITOR_REMOTE_HOST_STORE, RpcContext.getServiceContext().getRemoteHost());
//count up
getConcurrent(invoker, invocation).incrementAndGet();
}
//proceed invocation chain
//下面又会调用FilterChainBuilder的内部类CopyOfFilterChainNode的invoke()方法
return invoker.invoke(invocation);
}
...
}
@Activate(group = {CONSUMER})
public class RouterSnapshotFilter implements ClusterFilter, BaseFilter.Listener {
...
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
//接下来会调用AbstractClusterInvoker的invoke()方法
if (!switcher.isEnable()) {
return invoker.invoke(invocation);
}
if (!logger.isInfoEnabled()) {
return invoker.invoke(invocation);
}
if (!switcher.isEnable(invocation.getServiceModel().getServiceKey())) {
return invoker.invoke(invocation);
}
RpcContext.getServiceContext().setNeedPrintRouterSnapshot(true);
return invoker.invoke(invocation);
}
...
}
public abstract class AbstractClusterInvoker<T> implements ClusterInvoker<T> {
...
@Override
public Result invoke(final Invocation invocation) throws RpcException {
...
//下面会根据invocation信息列出所有的Invoker
//也就是通过DynamicDirectory.list()方法进行服务发现
//由于通过Directory获取Invoker对象列表
//通过了解RegistryDirectory可知,其中已经调用了Router进行过滤
//从而可以知道有哪些服务实例、有哪些Invoker
//由于一个服务实例会对应一个Invoker,所以目标服务实例集群已变成invokers了
List<Invoker<T>> invokers = list(invocation);
InvocationProfilerUtils.releaseDetailProfiler(invocation);
//通过SPI加载LoadBalance实例,也就是在这里选择出对应的负载均衡策略
LoadBalance loadbalance = initLoadBalance(invokers, invocation);
RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);
InvocationProfilerUtils.enterDetailProfiler(invocation, () -> "Cluster " + this.getClass().getName() + " invoke.");
try {
//调用由子类实现的抽象方法doInvoke()
//下面会由子类FailoverClusterInvoker执行doInvoke()方法
return doInvoke(invocation, invokers, loadbalance);
} finally {
InvocationProfilerUtils.releaseDetailProfiler(invocation);
}
}
protected List<Invoker<T>> list(Invocation invocation) throws RpcException {
//通过DynamicDirectory.list()进行服务发现
return getDirectory().list(invocation);
}
@Override
public Directory<T> getDirectory() {
return directory;
}
...
}
public class FailoverClusterInvoker<T> extends AbstractClusterInvoker<T> {
...
//该方法会找出一个Invoker
//把invocation交给多个Invokers里的一个去发起RPC调用
//其中会根据传入的loadbalance来实现负载均衡
public Result doInvoke(Invocation invocation, final List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
//下面先做一个引用赋值
List<Invoker<T>> copyInvokers = invokers;
//检查Invokers
checkInvokers(copyInvokers, invocation);
//从RPC调用里提取一个method方法名称,从而确定需要调用的是哪个方法
String methodName = RpcUtils.getMethodName(invocation);
//计算最多调用次数;因为Failover策略是,如果发现调用不成功会进行重试,但默认会最多调用3次来让调用成功
int len = calculateInvokeTimes(methodName);
//last exception.
RpcException le = null;
//构建了一个跟invokers数量相等的一个list
List<Invoker<T>> invoked = new ArrayList<Invoker<T>>(copyInvokers.size());//invoked invokers.
//基于计算出的调用次数,构建一个set;如果调用次数为3,那么意味着最多会调用3个provider服务实例
Set<String> providers = new HashSet<String>(len);
//对len次数进行循环
for (int i = 0; i < len; i++) {
//到i>0时,表示的是第一次调用失败,要开始进行重试了
if (i > 0) {
//检查当前服务实例是否被销毁
checkWhetherDestroyed();
//此时要调用DynamicDirectory进行一次invokers列表刷新
//因为第一次调用都失败了,所以有可能invokers列表出现了变化,因而需要刷新一下invokers列表
copyInvokers = list(invocation);
//check again
//再次check一下invokers是否为空
checkInvokers(copyInvokers, invocation);
}
//1.下面会调用AbstractClusterInvoker的select()方法
//select()方法会选择一个Invoker出来,具体逻辑是:
//首先尝试用负载均衡算法去选
//如果选出的Invoker是选过的或者不可用的,那么就直接reselect
//也就是对选过的找一个可用的,对选不出的直接挑选下一个
Invoker<T> invoker = select(loadbalance, invocation, copyInvokers, invoked);
invoked.add(invoker);
RpcContext.getServiceContext().setInvokers((List) invoked);
boolean success = false;
try {
//2.调用AbstractClusterInvoker的invokeWithContext()方法
//基于该Invoker发起RPC调用,并拿到一个result
Result result = invokeWithContext(invoker, invocation);
if (le != null && logger.isWarnEnabled()) {
logger.warn("...");
}
success = true;
return result;
} catch (RpcException e) {
//如果本次RPC调用失败了,那么就会有异常抛出来
if (e.isBiz()) {
throw e;
}
le = e;
} catch (Throwable e) {
le = new RpcException(e.getMessage(), e);
} finally {
if (!success) {
//下面会把出现RPC调用异常的进行设置,把本次调用失败的invoker地址添加到providers
providers.add(invoker.getUrl().getAddress());
}
}
}
//如果最后抛出如下这个异常,则说明本次RPC调用彻底失败了
throw new RpcException("...");
}
...
}
3.服务发现获取目标服务实例集群Invokers
服务发现获取目标服务实例集群Invokers的入口便是AbstractClusterInvoker的list()方法,该方法会调用AbstractDirectory的list()方法来获取目标服务实例集群。
在AbstractDirectory的list()方法中,可以发现目标服务实例集群invokers其实已经缓存在内存了,所以并没有直接去zk中进行获取。同时,该方法会根据缓存的目标服务实例集群invokers,调用AbstractDirectory的子类DynamicDirectory的doList()方法来获取合适的目标服务实例集群。
而在DynamicDirectory的doList()方法中,则会调用RouterChain的route()方法对目标服务实例集群进行过滤。
arduino
//-> AbstractClusterInvoker.invoke()
//-> AbstractClusterInvoker.list()
//-> AbstractDirectory.list()
//-> DynamicDirectory.doList()
//-> RouterChain.route()
swift
public abstract class AbstractClusterInvoker<T> implements ClusterInvoker<T> {
protected Directory<T> directory;
@Override
public Result invoke(final Invocation invocation) throws RpcException {
...
//下面会根据invocation信息列出所有的Invoker
//也就是通过DynamicDirectory.list()方法进行服务发现
//由于通过Directory获取Invoker对象列表
//通过了解RegistryDirectory可知,其中已经调用了Router进行过滤
//从而可以知道有哪些服务实例、有哪些Invoker
//由于一个服务实例会对应一个Invoker,所以目标服务实例集群已变成invokers了
List<Invoker<T>> invokers = list(invocation);
InvocationProfilerUtils.releaseDetailProfiler(invocation);
//通过SPI加载LoadBalance实例,也就是在这里选择出对应的负载均衡策略
LoadBalance loadbalance = initLoadBalance(invokers, invocation);
RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);
InvocationProfilerUtils.enterDetailProfiler(invocation, () -> "Cluster " + this.getClass().getName() + " invoke.");
try {
//调用由子类实现的抽象方法doInvoke()
//下面会由子类FailoverClusterInvoker执行doInvoke()方法
return doInvoke(invocation, invokers, loadbalance);
} finally {
InvocationProfilerUtils.releaseDetailProfiler(invocation);
}
}
protected List<Invoker<T>> list(Invocation invocation) throws RpcException {
//通过DynamicDirectory.list()进行服务发现
return getDirectory().list(invocation);
}
@Override
public Directory<T> getDirectory() {
return directory;
}
...
}
public abstract class AbstractDirectory<T> implements Directory<T> {
//All invokers from registry
private volatile BitList<Invoker<T>> invokers = BitList.emptyList();
//Valid Invoker. All invokers from registry exclude unavailable and disabled invokers.
private volatile BitList<Invoker<T>> validInvokers = BitList.emptyList();
...
@Override
public List<Invoker<T>> list(Invocation invocation) throws RpcException {
...
BitList<Invoker<T>> availableInvokers;
//use clone to avoid being modified at doList().
if (invokersInitialized) {
availableInvokers = validInvokers.clone();
} else {
availableInvokers = invokers.clone();
}
List<Invoker<T>> routedResult = doList(availableInvokers, invocation);
...
}
protected abstract List<Invoker<T>> doList(BitList<Invoker<T>> invokers, Invocation invocation) throws RpcException;
...
}
public abstract class DynamicDirectory<T> extends AbstractDirectory<T> implements NotifyListener {
...
@Override
public List<Invoker<T>> doList(BitList<Invoker<T>> invokers, Invocation invocation) {
if (forbidden && shouldFailFast) {
//1. No service provider
//2. Service providers are disabled
throw new RpcException(RpcException.FORBIDDEN_EXCEPTION, "...");
}
if (multiGroup) {
return this.getInvokers();
}
try {
//Get invokers from cache, only runtime routers will be executed.
//从缓存中获取invokers,只有运行中的routers才会被执行
List<Invoker<T>> result = routerChain.route(getConsumerUrl(), invokers, invocation);
return result == null ? BitList.emptyList() : result;
} catch (Throwable t) {
//2-1 - Failed to execute routing.
logger.error(CLUSTER_FAILED_SITE_SELECTION, "", "", "Failed to execute router: " + getUrl() + ", cause: " + t.getMessage(), t);
return BitList.emptyList();
}
}
...
}
public class RouterChain<T> {
...
public List<Invoker<T>> route(URL url, BitList<Invoker<T>> availableInvokers, Invocation invocation) {
if (RpcContext.getServiceContext().isNeedPrintRouterSnapshot()) {
return routeAndPrint(url, availableInvokers, invocation);
} else {
return simpleRoute(url, availableInvokers, invocation);
}
}
...
}
在AbstractDirectory的list()方法中,会获取缓存中的invokers进行处理,那么缓存中的invokers究竟是什么时候从zk中获取并进行缓存的呢?
其实就是在服务引用时创建动态代理的过程中,通过调用DynamicDirectory的subscribe()方法,从zk中获取服务实例并进行缓存的,其中的调用链如下所示:
arduino
//-> ReferenceConfig.get()
//-> ReferenceConfig.init()
//-> ReferenceConfig.createProxy()
//-> ReferenceConfig.createInvokerForRemote()
//-> protocolSPI.refer()
//-> RegistryProtocol.refer()
//-> RegistryProtocol.doRefer()
//-> RegistryProtocol.interceptInvoker()
//-> listener.onRefer()
//-> RegistryProtocol.getInvoker()
//-> RegistryProtocol.doCreateInvoker()
//-> directory.subscribe(toSubscribeUrl(urlToRegistry))
typescript
public class RegistryProtocol implements Protocol, ScopeModelAware {
...
protected <T> ClusterInvoker<T> doCreateInvoker(DynamicDirectory<T> directory, Cluster cluster, Registry registry, Class<T> type) {
...
//订阅服务,toSubscribeUrl()方法会将urlToRegistry中category参数修改为"providers,configurators,routers"
//下面会调用DynamicDirectory子类RegistryDirectory的subscribe()会进行服务发现,同时还会添加相应的监听器
//进行服务发现时,会把从注册中心拿到的服务实例集群invokers都初始化和缓存完毕
//并对每个服务实例都新建NettyClient来和provider建立好网络连接
//后面通过directory.list()获取服务实例集群invokers就会从缓存中获取了
directory.subscribe(toSubscribeUrl(urlToRegistry));
...
}
...
}
4.DynamicDirectory进行服务发现的流程
(1)subscribe()方法对服务订阅和发现
(2)doList()方法进行获取服务
(1)subscribe()方法对服务订阅和发现
bash
//-> ReferenceConfig.get()
//-> RegistryProtocol.doCreateInvoker()
//-> directory.subscribe(toSubscribeUrl(urlToRegistry))
//-> RegistryDirectory.subscribe()
//-> DynamicDirectory.subscribe()
//-> ListenerRegistryWrapper.subscribe()
//-> FailbackRegistry.subscribe()
//-> AbstractRegistry.subscribe() + FailbackRegistry.doSubscribe()
//-> ZookeeperRegistry.doSubscribe() + create()/notify() [通过zkClient对服务进行订阅和监听]
//-> FailbackRegistry.notify() [通知NotifyListener处理当前已有的URL等注册数据]
//-> AbstractRegistry.notify()
//-> RegistryDirectory.notify() [期间会通过NettyClient和provider建立网络连接]
//-> RegistryDirectory.toInvokers()
//-> DubboProtocol.refer()
//-> DubboProtocol.protocolBindingRefer() [构建Invoker即封装一个DubboInvoker]
//-> DubboProtocol.getClients() [DubboInvoker的构建过程便会通过NettyClient对服务实例建立网络连接]
//-> DubboProtocol.initClient()
//-> Exchangers.connect()
//-> new DubboInvoker()
scala
public class RegistryDirectory<T> extends DynamicDirectory<T> {
private final ModuleModel moduleModel;
private final ConsumerConfigurationListener consumerConfigurationListener;
private ReferenceConfigurationListener referenceConfigurationListener;
...
@Override
public void subscribe(URL url) {
//调用DynamicDirectory.subscribe()方法
super.subscribe(url);
if (moduleModel.getModelEnvironment().getConfiguration().convert(Boolean.class, org.apache.dubbo.registry.Constants.ENABLE_CONFIGURATION_LISTEN, true)) {
//将当前RegistryDirectory对象作为ConfigurationListener记录到consumerConfigurationListener中
consumerConfigurationListener.addNotifyListener(this);
referenceConfigurationListener = new ReferenceConfigurationListener(moduleModel, this, url);
}
}
...
}
//DynamicDirectory相当于2.7.x里的RegistryDirectory
//它是一个用来进行服务发现的组件,是一个可以动态管理可变的服务实例集群地址的组件
//当Consumer调用Provider时,便会用到该动态目录DynamicDirectory进行服务发现
//动态目录可以理解为:
//动态可变的一个目标服务实例的集群地址(invokers)
//有多少个目标服务实例就会有多少Invoker
//动态的意思其实就是:
//不仅可以通过主动查询来获取目标服务实例集群地址
//还可以在目标服务实例集群地址发生变化时,接收zk的推送并更新内存里的地址
//DynamicDirectory有两个重要的方法:
//1.subscribe()
//2.doList()
public abstract class DynamicDirectory<T> extends AbstractDirectory<T> implements NotifyListener {
...
public void subscribe(URL url) {
setSubscribeUrl(url);
//实现服务发现靠的就是下面这个方法
//此时会调用ListenerRegistryWrapper.subscribe()方法
registry.subscribe(url, this);
}
...
}
public class ListenerRegistryWrapper implements Registry {
//RegistryProtocol.export()方法中获取Registry时,这里会是一个ServiceDiscoveryRegistry
//RegistryProtocol.refer() -> RegistryProtocol.doCreateInvoker()时,这里会是一个ZookeeperRegistry
private final Registry registry;
...
public void subscribe(URL url, NotifyListener listener) {
...
//服务引用时下面会调用ZookeeperRegistry的父类FailbackRegistry的subscribe()方法
//服务发布时下面会调用ServiceDiscoveryRegistry的subscribe()方法
registry.subscribe(url, listener);
...
}
...
}
public abstract class FailbackRegistry extends AbstractRegistry {
...
public void subscribe(URL url, NotifyListener listener) {
//先执行父类的订阅过程,也就是调用AbstractRegistry.subscribe()
super.subscribe(url, listener);
...
//然后调用ZookeeperRegistry.doSubscribe()方法
doSubscribe(url, listener);
...
}
public abstract void doSubscribe(URL url, NotifyListener listener);
...
}
public abstract class AbstractRegistry implements Registry {
...
@Override
public void subscribe(URL url, NotifyListener listener) {
...
//这个url是当前要订阅的地址,也就是要关注的那个服务接口
//listener是那个服务的订阅监听,可能会施加多个监听器
//这些监听器会被加入到subscribed中该url所对应的set里面
//订阅和监听时,需要添加一个监听器,但这个NotifyListener并非是zk里面的监听器
Set<NotifyListener> listeners = subscribed.computeIfAbsent(url, n -> new ConcurrentHashSet<>());
listeners.add(listener);
}
...
}
public class ZookeeperRegistry extends CacheableFailbackRegistry {
...
public void doSubscribe(final URL url, final NotifyListener listener) {
...
//create "directories".
//尝试创建持久节点,主要是为了确保当前path在Zookeeper上存在
//比如会对"/dubbo/服务接口/providers"进行检查,如果存在就不处理,如果不存在就去进行创建
zkClient.create(root, false);
//Add children (i.e. service items).
//针对要订阅和发现的那个服务节点添加一个监听器
//而且第一次加监听器,就会直接把子节点列表返回
//这个子节点列表,就是指定的Provider服务实例集群地址列表
List<String> children = zkClient.addChildListener(path, zkListener);
...
//初次订阅时,会主动调用一次notify()方法,通知NotifyListener处理当前已有的URL等注册数据
//这里会调用FailbackRegistry.notify()方法
notify(url, listener, urls);
}
...
}
//这是一个支持故障和重试的抽象类
public abstract class FailbackRegistry extends AbstractRegistry {
...
protected void notify(URL url, NotifyListener listener, List<URL> urls) {
//在订阅和发现时,必然需要直接定位到对应的Providers集群地址
//所以这些地址需要存储在本地,这样才能方便后续通过directory获取,保证随时可以拿到对应的集群地址
...
//FailbackRegistry的doNotify()方法实际上就是调用父类AbstractRegistry.notify()方法,没有其他逻辑
doNotify(url, listener, urls);
...
}
protected void doNotify(URL url, NotifyListener listener, List<URL> urls) {
//FailbackRegistry的doNotify()方法实际上就是调用父类AbstractRegistry.notify()方法,没有其他逻辑
super.notify(url, listener, urls);
}
...
}
public abstract class AbstractRegistry implements Registry {
...
protected void notify(URL url, NotifyListener listener, List<URL> urls) {
...
for (Map.Entry<String, List<URL>> entry : result.entrySet()) {
String category = entry.getKey();
List<URL> categoryList = entry.getValue();
categoryNotified.put(category, categoryList);
//下面会调用RegistryDirectory的notify()方法,通过NettyClient建立网络连接
listener.notify(categoryList);
...
}
}
...
}
public class RegistryDirectory<T> extends DynamicDirectory<T> {
...
public synchronized void notify(List<URL> urls) {
//按照category进行分类,分成configurators、routers、providers三类
Map<String, List<URL>> categoryUrls = urls.stream()
.filter(Objects::nonNull)
.filter(this::isValidCategory)
.filter(this::isNotCompatibleFor26x)
.collect(Collectors.groupingBy(this::judgeCategory));
//获取configurators类型的URL,并转换成Configurator对象
List<URL> configuratorURLs = categoryUrls.getOrDefault(CONFIGURATORS_CATEGORY, Collections.emptyList());
this.configurators = Configurator.toConfigurators(configuratorURLs).orElse(this.configurators);
//获取routers类型的URL,并转成Router对象,添加到RouterChain中
List<URL> routerURLs = categoryUrls.getOrDefault(ROUTERS_CATEGORY, Collections.emptyList());
toRouters(routerURLs).ifPresent(this::addRouters);
//providers
//获取providers类型的URL,调用refreshOverrideAndInvoker()方法进行处理
List<URL> providerURLs = categoryUrls.getOrDefault(PROVIDERS_CATEGORY, Collections.emptyList());
...
refreshOverrideAndInvoker(providerURLs);
}
private synchronized void refreshOverrideAndInvoker(List<URL> urls) {
refreshInvoker(urls);
}
private void refreshInvoker(List<URL> invokerUrls) {
...
//将invokerUrls转换为对应的Invoker映射关系
Map<URL, Invoker<T>> newUrlInvokerMap = toInvokers(oldUrlInvokerMap, invokerUrls);
...
}
private Map<URL, Invoker<T>> toInvokers(Map<URL, Invoker<T>> oldUrlInvokerMap, List<URL> urls) {
...
//这里通过Protocol.refer()方法创建对应的Invoker对象
//比如首先会调用Protocol$Adaptive.refer()
//然后调用ProtocolSerializationWrapper.refer()
//接着调用ProtocolFilterWrapper.refer()
//然后调用ProtocolListenerWrapper.refer()
//最后调用DubboProtocol.refer()
invoker = protocol.refer(serviceType, url);
...
}
...
}
public class DubboProtocol extends AbstractProtocol {
...
public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
checkDestroyed();
return protocolBindingRefer(type, url);
}
public <T> Invoker<T> protocolBindingRefer(Class<T> serviceType, URL url) throws RpcException {
checkDestroyed();
//进行序列化优化,注册需要优化的类
optimizeSerialization(url);
//create rpc invoker,创建DubboInvoker对象
//首先将url传入getClients()方法中,针对目标服务实例进行网络连接
//然后再根据这个目标服务实例的url,构建一个DubboInvoker
DubboInvoker<T> invoker = new DubboInvoker<T>(serviceType, url, getClients(url), invokers);
//将上面创建的DubboInvoker对象添加到invoker集合中
invokers.add(invoker);
return invoker;
}
private ExchangeClient[] getClients(URL url) {
//CONNECTIONS_KEY参数值决定了后续建立连接的数量
int connections = url.getParameter(CONNECTIONS_KEY, 0);
//如果没有连接数的相关配置,默认使用共享连接的方式
if (connections == 0) {
//确定建立共享连接的条数,默认只建立一条共享连接
String shareConnectionsStr = StringUtils.isBlank(url.getParameter(SHARE_CONNECTIONS_KEY, (String) null))
? ConfigurationUtils.getProperty(url.getOrDefaultApplicationModel(), SHARE_CONNECTIONS_KEY, DEFAULT_SHARE_CONNECTIONS)
: url.getParameter(SHARE_CONNECTIONS_KEY, (String) null);
connections = Integer.parseInt(shareConnectionsStr);
//创建公共ExchangeClient集合
List<ReferenceCountExchangeClient> shareClients = getSharedClient(url, connections);
//整理要返回的ExchangeClient集合
ExchangeClient[] clients = new ExchangeClient[connections];
Arrays.setAll(clients, shareClients::get);
return clients;
}
//整理要返回的ExchangeClient集合
ExchangeClient[] clients = new ExchangeClient[connections];
for (int i = 0; i < clients.length; i++) {
//不使用公共连接的情况下,会创建单独的ExchangeClient实例
clients[i] = initClient(url);
}
return clients;
}
private ExchangeClient initClient(URL url) {
//获取客户端类型,并检查
String str = url.getParameter(CLIENT_KEY, url.getParameter(SERVER_KEY, DEFAULT_REMOTING_CLIENT));
if (StringUtils.isNotEmpty(str) && !url.getOrDefaultFrameworkModel().getExtensionLoader(Transporter.class).hasExtension(str)) {
throw new RpcException("Unsupported client type: " + str + "," +
" supported client type is " + StringUtils.join(url.getOrDefaultFrameworkModel().getExtensionLoader(Transporter.class).getSupportedExtensions(), " "));
}
try {
url = new ServiceConfigURL(DubboCodec.NAME, url.getUsername(), url.getPassword(), url.getHost(), url.getPort(), url.getPath(), url.getAllParameters());
//设置Codec2的扩展名
url = url.addParameter(CODEC_KEY, DubboCodec.NAME);
//设置默认的心跳间隔
url = url.addParameterIfAbsent(HEARTBEAT_KEY, String.valueOf(DEFAULT_HEARTBEAT));
//如果配置了延迟创建连接的特性,则创建LazyConnectExchangeClient
//否则,调用Exchangers的connect()方法建立网络连接
return url.getParameter(LAZY_CONNECT_KEY, false)
? new LazyConnectExchangeClient(url, requestHandler)
: Exchangers.connect(url, requestHandler);
} catch (RemotingException e) {
throw new RpcException("Fail to create remoting client for service(" + url + "): " + e.getMessage(), e);
}
}
...
}
(2)doList()方法进行获取服务
kotlin
public abstract class DynamicDirectory<T> extends AbstractDirectory<T> implements NotifyListener {
...
@Override
public List<Invoker<T>> doList(BitList<Invoker<T>> invokers, Invocation invocation) {
if (forbidden && shouldFailFast) {
//检测forbidden字段,当该字段在refreshInvoker()过程中设置为true时,表示无Provider可用,直接抛出异常
//1.No service provider
//2.Service providers are disabled
throw new RpcException(RpcException.FORBIDDEN_EXCEPTION, "...");
}
if (multiGroup) {
//multiGroup为true时的特殊处理
//在refreshInvoker()方法中针对multiGroup为true的场景,已经使用Router进行了筛选,所以这里直接返回接口
return this.getInvokers();
}
try {
//会有很多种Router路由策略,比如TagRouter、ServiceRouter、AppRouter等;
//当调用Provider时,就可以根据tag、service、app等各种配置进行筛选,把一些特定实例的provider筛选出来进行访问
//比如灰度发布,对于Provider现在需要灰度发布一台新机器,跑的是新版本,而另外2台机器依旧是旧版本
//这时就需要所提供的Provider服务,必须要能把请求分发给老版本的旧机器,而新版本的新机器则暂时还不能访问或者只分发一点点流量
//Get invokers from cache, only runtime routers will be executed.
//从缓存中获取invokers,只有运行中的routers才会被执行
//也就是通过RouterChain.route()方法路由Invoker集合,最终得到符合路由条件的Invoker集合
List<Invoker<T>> result = routerChain.route(getConsumerUrl(), invokers, invocation);
return result == null ? BitList.emptyList() : result;
} catch (Throwable t) {
logger.error("Failed to execute router: " + getUrl() + ", because: " + t.getMessage(), t);
return BitList.emptyList();
}
}
...
}
//Router chain
//路由链条其实就是一些路由规则
//通过这些路由规则的过滤,能够把可以用来访问的目标服务实例invokers筛选出来
//使用了责任链模式的链条有:filter链条,invoker链条,router链条
//会有很多种Router路由策略,比如TagRouter、ServiceRouter、AppRouter等
//当调用Provider时,就可以根据tag、service、app等各种配置进行筛选,把一些特定实例的provider筛选出来进行访问
//比如灰度发布,对于Provider现在需要灰度发布一台新机器,跑的是新版本,而另外2台机器依旧是旧版本
//这时就需要所提供的Provider服务,必须要能把请求分发给老版本的旧机器,而新版本的新机器则暂时还不能访问或者只分发一点点流量
public class RouterChain<T> {
//当前RouterChain中要使用的Router集合
private volatile List<Router> routers = Collections.emptyList();
//RouterChain中的链表头节点
private volatile StateRouter<T> headStateRouter;
...
public List<Invoker<T>> route(URL url, BitList<Invoker<T>> availableInvokers, Invocation invocation) {
if (RpcContext.getServiceContext().isNeedPrintRouterSnapshot()) {
return routeAndPrint(url, availableInvokers, invocation);
} else {
return simpleRoute(url, availableInvokers, invocation);
}
}
public List<Invoker<T>> simpleRoute(URL url, BitList<Invoker<T>> availableInvokers, Invocation invocation) {
BitList<Invoker<T>> resultInvokers = availableInvokers.clone();
//1.route state router
//从头开始执行StateRouter链里的每个StateRouter的route()方法
resultInvokers = headStateRouter.route(resultInvokers, url, invocation, false, null);
if (resultInvokers.isEmpty() && (shouldFailFast || routers.isEmpty())) {
printRouterSnapshot(url, availableInvokers, invocation);
return BitList.emptyList();
}
if (routers.isEmpty()) {
return resultInvokers;
}
List<Invoker<T>> commonRouterResult = resultInvokers.cloneToArrayList();
//2.route common router
//遍历routers字段,逐个调用Router对象的route()方法,对invokers集合进行过滤
for (Router router : routers) {
//Copy resultInvokers to a arrayList. BitList not support
RouterResult<Invoker<T>> routeResult = router.route(commonRouterResult, url, invocation, false);
commonRouterResult = routeResult.getResult();
if (CollectionUtils.isEmpty(commonRouterResult) && shouldFailFast) {
printRouterSnapshot(url, availableInvokers, invocation);
return BitList.emptyList();
}
//stop continue routing
if (!routeResult.isNeedContinueRoute()) {
return commonRouterResult;
}
}
if (commonRouterResult.isEmpty()) {
printRouterSnapshot(url, availableInvokers, invocation);
return BitList.emptyList();
}
return commonRouterResult;
}
...
}
5.构造DubboInvoker并建立网络连接的过程
DubboProtocol的protocolBindingRefer()方法会先通过getClients()方法建立网络连接,然后才封装一个DubboInvoker对象进行返回。
arduino
//-> ReferenceConfig.get()
//...
//-> DubboProtocol.refer()
//-> DubboProtocol.protocolBindingRefer()
//-> DubboProtocol.getClients()
//-> DubboProtocol.getSharedClient()
//-> DubboProtocol.buildReferenceCountExchangeClientList()
//-> DubboProtocol.buildReferenceCountExchangeClient()
//-> DubboProtocol.initClient()
//-> Exchangers.connect(url, requestHandler)
//-> getExchanger(url).connect(url, handler)
//-> Exchanger.connect(url, handler)
//-> HeaderExchanger.connect()
//-> Transporters.connect()
//-> Transporters.getTransporter(url).connect(url, handler)
//-> NettyTransporter.connect()
//-> new NettyClient(url, handler) [构建NettyClient发起连接]
//-> new AbstractClient(url, handler)
//-> NettyClient.doOpen() + NettyClient.doConnect()
java
public class DubboProtocol extends AbstractProtocol {
//<host:port,Exchanger>
//Map<String, List<ReferenceCountExchangeClient>
private final Map<String, Object> referenceClientMap = new ConcurrentHashMap<>();
...
public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
checkDestroyed();
return protocolBindingRefer(type, url);
}
public <T> Invoker<T> protocolBindingRefer(Class<T> serviceType, URL url) throws RpcException {
checkDestroyed();
//进行序列化优化,注册需要优化的类
optimizeSerialization(url);
//create rpc invoker,创建DubboInvoker对象
//首先将url传入getClients()方法中,针对目标服务实例进行网络连接
//然后再根据这个目标服务实例的url,构建一个DubboInvoker
DubboInvoker<T> invoker = new DubboInvoker<T>(serviceType, url, getClients(url), invokers);
//将上面创建的DubboInvoker对象添加到invoker集合中
invokers.add(invoker);
return invoker;
}
private ExchangeClient[] getClients(URL url) {
//CONNECTIONS_KEY参数值决定了后续建立连接的数量
int connections = url.getParameter(CONNECTIONS_KEY, 0);
//如果没有连接数的相关配置,默认使用共享连接的方式
if (connections == 0) {
//确定建立共享连接的条数,默认只建立一条共享连接
String shareConnectionsStr = StringUtils.isBlank(url.getParameter(SHARE_CONNECTIONS_KEY, (String) null))
? ConfigurationUtils.getProperty(url.getOrDefaultApplicationModel(), SHARE_CONNECTIONS_KEY, DEFAULT_SHARE_CONNECTIONS)
: url.getParameter(SHARE_CONNECTIONS_KEY, (String) null);
connections = Integer.parseInt(shareConnectionsStr);
//创建公共ExchangeClient集合
List<ReferenceCountExchangeClient> shareClients = getSharedClient(url, connections);
//整理要返回的ExchangeClient集合
ExchangeClient[] clients = new ExchangeClient[connections];
Arrays.setAll(clients, shareClients::get);
return clients;
}
//整理要返回的ExchangeClient集合
ExchangeClient[] clients = new ExchangeClient[connections];
for (int i = 0; i < clients.length; i++) {
//不使用公共连接的情况下,会创建单独的ExchangeClient实例
clients[i] = initClient(url);
}
return clients;
}
private List<ReferenceCountExchangeClient> getSharedClient(URL url, int connectNum) {
//获取对端的地址(host:port)
String key = url.getAddress();
//从referenceClientMap集合中,获取与该地址连接的ReferenceCountExchangeClient集合
Object clients = referenceClientMap.get(key);
if (clients instanceof List) {
List<ReferenceCountExchangeClient> typedClients = (List<ReferenceCountExchangeClient>) clients;
//检测上述客户端集合是否全部可用
if (checkClientCanUse(typedClients)) {
//客户端全部可用时
batchClientRefIncr(typedClients);
return typedClients;
}
}
List<ReferenceCountExchangeClient> typedClients = null;
synchronized (referenceClientMap) {
for (; ;) {
//guarantee just one thread in loading condition.
//And Other is waiting It had finished.
clients = referenceClientMap.get(key);
if (clients instanceof List) {
typedClients = (List<ReferenceCountExchangeClient>) clients;
//double check,再次检测客户端是否可用
if (checkClientCanUse(typedClients)) {
batchClientRefIncr(typedClients);
return typedClients;
} else {
referenceClientMap.put(key, PENDING_OBJECT);
break;
}
} else if (clients == PENDING_OBJECT) {
try {
referenceClientMap.wait();
} catch (InterruptedException ignored) {
}
} else {
referenceClientMap.put(key, PENDING_OBJECT);
break;
}
}
}
try {
//connectNum must be greater than or equal to 1
//至少一个共享连接
connectNum = Math.max(connectNum, 1);
//If the clients is empty, then the first initialization is
if (CollectionUtils.isEmpty(typedClients)) {
//如果当前Clients集合为空,则直接通过initClient()方法初始化所有共享客户端
typedClients = buildReferenceCountExchangeClientList(url, connectNum);
} else {
//如果只有部分共享客户端不可用,则只需要处理这些不可用的客户端
for (int i = 0; i < typedClients.size(); i++) {
ReferenceCountExchangeClient referenceCountExchangeClient = typedClients.get(i);
//If there is a client in the list that is no longer available, create a new one to replace him.
if (referenceCountExchangeClient == null || referenceCountExchangeClient.isClosed()) {
typedClients.set(i, buildReferenceCountExchangeClient(url));
continue;
}
//增加引用
referenceCountExchangeClient.incrementAndGetCount();
}
}
} finally {
synchronized (referenceClientMap) {
if (typedClients == null) {
referenceClientMap.remove(key);
} else {
referenceClientMap.put(key, typedClients);
}
referenceClientMap.notifyAll();
}
}
return typedClients;
}
private List<ReferenceCountExchangeClient> buildReferenceCountExchangeClientList(URL url, int connectNum) {
List<ReferenceCountExchangeClient> clients = new ArrayList<>();
for (int i = 0; i < connectNum; i++) {
clients.add(buildReferenceCountExchangeClient(url));
}
return clients;
}
private ReferenceCountExchangeClient buildReferenceCountExchangeClient(URL url) {
ExchangeClient exchangeClient = initClient(url);
ReferenceCountExchangeClient client = new ReferenceCountExchangeClient(exchangeClient, DubboCodec.NAME);
//read configs
int shutdownTimeout = ConfigurationUtils.getServerShutdownTimeout(url.getScopeModel());
client.setShutdownWaitTime(shutdownTimeout);
return client;
}
private ExchangeClient initClient(URL url) {
//获取客户端类型,并检查
String str = url.getParameter(CLIENT_KEY, url.getParameter(SERVER_KEY, DEFAULT_REMOTING_CLIENT));
if (StringUtils.isNotEmpty(str) && !url.getOrDefaultFrameworkModel().getExtensionLoader(Transporter.class).hasExtension(str)) {
throw new RpcException("Unsupported client type: " + str + "," +
" supported client type is " + StringUtils.join(url.getOrDefaultFrameworkModel().getExtensionLoader(Transporter.class).getSupportedExtensions(), " "));
}
try {
url = new ServiceConfigURL(DubboCodec.NAME, url.getUsername(), url.getPassword(), url.getHost(), url.getPort(), url.getPath(), url.getAllParameters());
//设置Codec2的扩展名
url = url.addParameter(CODEC_KEY, DubboCodec.NAME);
//设置默认的心跳间隔
url = url.addParameterIfAbsent(HEARTBEAT_KEY, String.valueOf(DEFAULT_HEARTBEAT));
//如果配置了延迟创建连接的特性,则创建LazyConnectExchangeClient
//否则,调用Exchangers的connect()方法建立网络连接
return url.getParameter(LAZY_CONNECT_KEY, false)
? new LazyConnectExchangeClient(url, requestHandler)
: Exchangers.connect(url, requestHandler);
} catch (RemotingException e) {
throw new RpcException("Fail to create remoting client for service(" + url + "): " + e.getMessage(), e);
}
}
...
}
public class Exchangers {
...
public static ExchangeClient connect(URL url, ExchangeHandler handler) throws RemotingException {
...
//下面会调用到HeaderExchanger.connect()方法
//传入的handler是DubboProtocol的requestHandler
return getExchanger(url).connect(url, handler);
}
public static Exchanger getExchanger(URL url) {
String type = url.getParameter(Constants.EXCHANGER_KEY, Constants.DEFAULT_EXCHANGER);
//根据SPI机制,通过model组件体系去拿到对应的SPI扩展实现类实例
//比如获取到的是一个HeaderExchanger
return url.getOrDefaultFrameworkModel().getExtensionLoader(Exchanger.class).getExtension(type);
}
...
}
public class HeaderExchanger implements Exchanger {
public static final String NAME = "header";
//NettyClient -> MultiMessageHandler -> HeartbeatHandler -> AllChannelHandler -> DecodeHandler -> HeaderExchangeHandler -> requestHandler
//HeaderExchangeClient -> NettyClient
@Override
public ExchangeClient connect(URL url, ExchangeHandler handler) throws RemotingException {
//传入的handler是DubboProtocol的requestHandler
return new HeaderExchangeClient(Transporters.connect(url, new DecodeHandler(new HeaderExchangeHandler(handler))), true);
}
...
}
public class Transporters {
...
public static Client connect(URL url, ChannelHandler... handlers) throws RemotingException {
...
//下面会调用NettyTransporter.connect()方法
//传入的handler为装饰了DubboProtocol的requestHandler
//返回一个NettyClient
return getTransporter(url).connect(url, handler);
}
public static Transporter getTransporter(URL url) {
//下面使用了getAdaptiveExtension()的自适应机制,针对接口动态生成代码然后创建代理类
//代理类的方法,会根据url的参数动态提取对应的实现类的name名称,以及获取真正的需要使用的实现类
//有了真正的实现类后,就可以去调用实现类的extension实例的方法了
//比如下面会获取到一个NettyTransporter实例
return url.getOrDefaultFrameworkModel().getExtensionLoader(Transporter.class).getAdaptiveExtension();
}
...
}
public class NettyTransporter implements Transporter {
...
public Client connect(URL url, ChannelHandler handler) throws RemotingException {
//传入的handler为装饰了DubboProtocol的requestHandler
//返回一个NettyClient
return new NettyClient(url, handler);
}
...
}
public abstract class AbstractClient extends AbstractEndpoint implements Client {
...
public AbstractClient(URL url, ChannelHandler handler) throws RemotingException {
//调用父类的构造方法
super(url, handler);
//解析URL,初始化executor
initExecutor(url);
//初始化底层的NIO库的相关组件
doOpen();
//connect. 创建底层连接
connect();
...
}
protected void connect() throws RemotingException {
...
doConnect();
...
}
...
}
public class NettyClient extends AbstractClient {
...
public NettyClient(final URL url, final ChannelHandler handler) throws RemotingException {
super(url, wrapChannelHandler(url, handler));
}
protected void doOpen() throws Throwable {
//创建NettyClientHandler,handler一般来说是用来处理网络请求的
final NettyClientHandler nettyClientHandler = createNettyClientHandler();
//创建Bootstrap,对于NettyClient必须构建一个Bootstrap
bootstrap = new Bootstrap();
initBootstrap(nettyClientHandler);
}
protected void doConnect() throws Throwable {
long start = System.currentTimeMillis();
//bootstrap.connect会对server端发起一个网络连接
//但这个网络连接,并不是立刻就可以做好的
ChannelFuture future = bootstrap.connect(getConnectAddress());
...
boolean ret = future.awaitUninterruptibly(getConnectTimeout(), MILLISECONDS);
...
//如果连接成功,此时就可以通过future拿到一个Channel
//这个Channel代表着Client端和Server端Provider服务实例建立好的网络连接
Channel newChannel = future.channel();
...
}
...
}