文章目录
- 一、服务引用流程简述:
- 二、引用源码,从ReferenceConfig 的get开始
- 1、我们先看看Injvm协议的引用:
- 2、protocol的远程引用分两种情况 ①、指定url点对点直接引用 ②、引用注册中心所有proviers
- 3、 引用注册中心所有proviers流程
- 4、看看cluster.join(directory)如何封装RegistryDirectory对象作为invoker返回
- 5、得知join就是装饰器模式一样;把类注入进去;方便扩展功能
- 6、先探究下mock和failover封装的inovker的作用
- 7、走了mockCluster逻辑会走到FailoverClusterInvoker
- 8、此时我们得到了整个注册中心的所有url代表: mockClusterInovker(registryDirectory)调用对象,和 代表直连的 dubboInvoker(client) 调用对象;
- 9、看getProxy如何生成invoker的代理的:
- 10、看看生成的proxy代理类长什么样:
- 三、代理得到的invoker对象封装情况:
- 总结
一、服务引用流程简述:
1、如果本地有提供者或指定Injvm 则JVM引用得到invoker对象 (new InjvmInvoker)
2、远程服务引用得到invoker对象 (new DubboInvoker(registryDirector))(此时还没有得到服务提供者url)
3、web服务启动( 默认netty,new Sock(ip:port))
4、注册consumer节点,订阅providers、routes、configurators节点 (方便获取到providersUrl生成invoker对象)
5、把远程调用对象,代理一下返回给用户
二、引用源码,从ReferenceConfig 的get开始
1、我们先看看Injvm协议的引用:
2、protocol的远程引用分两种情况 ①、指定url点对点直接引用 ②、引用注册中心所有proviers
先看看直接url点对点直接引用: 此时url配置假设为 dubbo://ip:port?interface=xx&&……
所以refprotocol.refer(this.interfaceClass, monitorUrl) refprotocol扩展对象为dubboProtocol;同理会经过linstenerWrapper和filterWraper的包装
现在我们得到DbuboInvoker对象,假设用户调用起来,看看有什么作用:
我们接着看看如何开启web服务的:
上面doOpen 开启netty client服务,然后connet进行连接;netty相关代码暂不分析
3、 引用注册中心所有proviers流程
refprotocol.refer(this.interfaceClass, monitorUrl); 因为url是Registry开头的,扩展实现类是RegistryProtocol;
同理会经过listerwrapper和filterWrapper类;不过此处因为是registry开头,不经过处理;直接调用到RegistryProtocol
那我们看这个类的refer怎么处理的:
public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
url = url.setProtocol(url.getParameter("registry", "dubbo")).removeParameter("registry");//url设置为rpc协议
Registry registry = this.registryFactory.getRegistry(url);//得到注册中心对象(和服务暴露一致,期间会开启zk连接并监听重连重新注册以注册的节点)
if (RegistryService.class.equals(type)) {
return this.proxyFactory.getInvoker(registry, type, url);//如果是注册中心接口服务,则直接返回其代理;一般不会走到这
} else {
Map<String, String> qs = StringUtils.parseQueryString(url.getParameterAndDecoded("refer"));
String group = (String)qs.get("group");
return group == null || group.length() <= 0 || Constants.COMMA_SPLIT_PATTERN.split(group).length <= 1 && !"*".equals(group) ? this.doRefer(this.cluster, registry, type, url) : //这个cluster是一个自动注入的自适应类
this.doRefer(this.getMergeableCluster(), registry, type, url);//如果group有多个,则使用MergeableCluster实现
} //本地方法,继续服务引用
}
注册consumer节点,就是zkclient.create节点,和服务暴露那边的一致
订阅providers/configurators/routes节点,就是创建这3个节点,并监听子类; 和服务暴露那边一致;只不过此处的linster是RegistryDirectory;我们看看订阅后它怎么生产invoker的:
此时我们已经在RegistryProtocol的doRefer中new了RegistryDirectory对象,并注册消费者节点,订阅providers、routers/configurators节点;
以及监听到提供者后RegistryDirectory如何自动生成或刷新invoker的;
4、看看cluster.join(directory)如何封装RegistryDirectory对象作为invoker返回
看到spi的扩展类,知道它会用mockClusterWrapper封装FailoverCluster;我们看看join做了什么
5、得知join就是装饰器模式一样;把类注入进去;方便扩展功能
6、先探究下mock和failover封装的inovker的作用
现在我们已经是mockClusterWrapper(directory,FailoverCluster)的封装了; 为了方便看类的功能;先假设用户得到inovker的代理类,进行调用了;它会先走到mockCluster的invoker
接着看mock怎么实现的
再看看如何选择invoke:
7、走了mockCluster逻辑会走到FailoverClusterInvoker
它会先走到它的父类;
然后看看具体子类FailoverClusterInvoker怎么做服务重试的
看看默认的负载均衡怎么实现
8、此时我们得到了整个注册中心的所有url代表: mockClusterInovker(registryDirectory)调用对象,和 代表直连的 dubboInvoker(client) 调用对象;
private T createProxy(Map<String, String> map) {
……省略injvm判断
while(var17.hasNext()) {
monitorUrl = (URL)var17.next();
invokers.add(refprotocol.refer(this.interfaceClass, monitorUrl));
if ("registry".equals(monitorUrl.getProtocol())) {
registryURL = monitorUrl;
}
}
if (registryURL != null) {
u = registryURL.addParameter("cluster", "available");
this.invoker = cluster.join(new StaticDirectory(u, invokers));
} else {
this.invoker = cluster.join(new StaticDirectory(invokers));
}
……省略check参数获取
if (c && !this.invoker.isAvailable()) {
;
}
return proxyFactory.getProxy(this.invoker);
看cluster.join(new StaticDirectory(invoker)) 最后还用mockClusterInvoker再包一层StaticDirecotry目录,静态缓存了下invoker
9、看getProxy如何生成invoker的代理的:
proxyFactory 是一个自适应类,默认用javassist字节码工具生成代理; 有一个包装实现类StubProxyFactoryWrapper;所以我们从这里开始
10、看看生成的proxy代理类长什么样:
三、代理得到的invoker对象封装情况:
引用流程时序图:
总结
本节分析了服务引用大概流程:本地服务引用、远程单点服务引用、远程注册中心引用、注册和订阅、监听动作、服务降级、负载均衡 ;后续分析下netty端的通信和消费者的调用流程