Dubbo原理<四> 服务引用


一、服务引用流程简述:

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端的通信和消费者的调用流程

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值