本文共 3688 字,大约阅读时间需要 12 分钟。
文章目录
一、服务引用流程简述:
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注册consumer节点,就是zkclient.create节点,和服务暴露那边的一致 订阅providers/configurators/routes节点,就是创建这3个节点,并监听子类; 和服务暴露那边一致;只不过此处的linster是RegistryDirectory;我们看看订阅后它怎么生产invoker的:Invoker refer(Class 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 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实现 } //本地方法,继续服务引用}
此时我们已经在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(Mapmap) { ……省略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端的通信和消费者的调用流程
转载地址:https://blog.csdn.net/qq_32129371/article/details/114935595 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!