为什么80%的码农都做不了架构师?>>>   

dubbo 服务引用过程

dubbo 的使用过程中消费者端会依赖服务端提供的 api 包(接口 jar 包) , 这些 api 包中只含有服务的 Interface 的 class 文件 , 在进行服务调用的时候使用 Interface 的一个引用,就可以进行远程的调用了,因为 dubbo 在客户端动态的生成了一个该 Interface 类型的代理类。在这个代理类中封装了远程服务调用的组件。获取这个 Interface 类型的代理对象的实例通过 spring IOC 容器 ,自动注入的方式或者通过 getBean 的方式。服务引用的入口代码:

com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler
com.alibaba.dubbo.config.spring.schema.DubboBeanDefinitionParser
com.alibaba.dubbo.config.spring.ReferenceBean

ReferenceBean 实现了 spring 的 FactoryBean 接口 , 该接口有一个 T getObject() 函数 ,dubbo 服务引用的开端就是在实现的这个 getObject() 函数中。当对任意服务 Interface 进行自动注入或者 getBean 获取时,就会触发服务的引用过程。

服务引用分为和服务提供者在同一个 JVM 实例中和在不同的 JVM 引用,和服务提供者在同一 JVM 实例中引用不会打开网络连接,同一 JVM 实例内调用不需要经过网络传输过程。在和服务提供者不同的 JVM 实例内引用时就必须打开网络连接,否则无法调用远程服务。

和服务提供者在不同 JVM 实例中引用,首先消费者要去注册中心进行注册, 接下来订阅所引用的服务。当服务提供者接收到消费者的订阅消息后会去注册中心查找已经注册的所有服务 , 然后匹配哪一个服务是当前消费者正在订阅的服务 , 如果匹配成功了就会通过注册中心通知消费者找到了消费者订阅的服务,消费者接收到注册中心发送的匹配服务成功消息后 , 会调用消费者注册的订阅通知监听 (NotifyListener), NotifyListener 中的 notify 会被调用 。 dubbo 提供了一个 RegistryDirectory 实现了 NotifyListener 接口 , 在 notify 函数中去刷新 Invoker (refreshInvoker) 。这时候会去创建一个新的 Invoker , 创建的这个 Invoker 还是和之前博客中讨论过的创建 Invoker 的过程一样, Invoker 会被 Filter 、 Listener 包装。在创建这个 Invoker 的过程中也会打开网络连接。

这里使用的注册中心是 multicast 。 zookeeper , redis 注册中心的具体实现方式不同。如果在消费者服务引用的过程中,服务提供者没有正常启动的话,是不会去进行打开网络连接操作的,如果在消费者连接提供者的过程中提供者挂掉了抛出异常 RemotingException  。

打开网络连接

消费者在引用服务的过程中如果和提供者不在同一 JVM 实例内,需要去打开网络连接,来和服务提供者进行网络通信。打开网络连接的过程和服务端在网络中暴露服务的顺序一致 Transporter , Exchanger , ExchangeClient 可选的实现有 NettyClient (默认) , MinaClient , GrizzlyClient 。消费者建立客户端打开网络连接之后要和所订阅的服务端建立连接。Interface 引用 , Invoker  , ExchangeClient  , Provider 之间的关系大致是这样:

每一个服务引用都可能对应多个 Invoker , 每一个 Invoker 指向了一个 Provider ,消费者内部会开启多个客户端与提供者开启的一个服务端进行通信。当使用服务引用调用服务时,就可以在多个 Invoker 之间进行负载均衡。如果每个 Invoker 只有一个 Client,这样称为共享连接。每一个服务引用也可以使用多个网络连接,在 <dubbo:reference connections="3" /> 进行配置 , 默认使用共享网络连接。

创建服务存根接口的代理对象

通过 ProxyFactory 扩展点 getProxy 来获取一个代理对象的实例 ,dubbo 默认使用的是 JavassistProxyFactory 扩展 , 动态的生成一个代理类和这个代理类的实例对象 。我的 Interface 代码 :

package net.j4love.dubbo.quickstart.provider;public interface DemoService {String echoWithCurrentTime(String src);
}

生成的接口代理类代码 :

package com.alibaba.dubbo.common.bytecode;public class com.alibaba.dubbo.common.bytecode.proxy0
implements interface net.j4love.dubbo.quickstart.provider.DemoService ,interface com.alibaba.dubbo.rpc.service.EchoService {// 存储的是所有实现的接口中的 methodpublic static java.lang.reflect.Method[] methods;private java.lang.reflect.InvocationHandler handler;public proxy0(java.lang.reflect.InvocationHandler $1) {handler=$1;}public java.lang.String echoWithCurrentTime(java.lang.String $1) {Object[] args = new Object[1];args[0] = ($w)$1;Object ret = handler.invoke(this, methods[0], args);return (java.lang.String)ret;}public java.lang.Object $echo(java.lang.Object $1) {Object[] args = new Object[1];args[0] = ($w)$1;Object ret = handler.invoke(this, methods[1], args);return (java.lang.Object)ret;}
}

生成的 com.alibaba.dubbo.common.bytecode.Proxy 的实现类代码 :

public class com.alibaba.dubbo.common.bytecode.Proxy0 extends
com.alibaba.dubbo.common.bytecode.Proxy {public Proxy0() {}public Object newInstance(java.lang.reflect.InvocationHandler h) {return new com.alibaba.dubbo.common.bytecode.proxy0($1);}
}

数字 0 是自增生成的 , 从 0 开始自增。

回声测试

所有的动态生成的引用接口代理类都实现了 com.alibaba.dubbo.rpc.service.EchoService 这个接口,获取到的引用可以强制转换成 EchoService  调用 $echo 函数来测试服务是否可用。

泛化调用

泛化调用是用 interface com.alibaba.dubbo.rpc.service.GenericService 接口来替代自定义的服务接口,通过  $invoke 函数来调用远程服务 , 这种方式适用于消费者端本地没有服务提供者端的接口 jar 包时,但是却知道接口的全名称 , 接口全名称是必须知道的因为要靠这个名称去注册中心寻找是否有注册的服务提供者。泛化调用只需要进行配置就可使用  , generic 设置为 true:

<dubbo:reference id="demoService"version="1.0.0"generic="true"interface="net.j4love.dubbo.quickstart.provider.DemoService" />

转载于:https://my.oschina.net/j4love/blog/1817698

理解 Dubbo 服务引用相关推荐

  1. Dubbo服务引用过程

    Dubbo服务引用 大致流程 Provider将服务暴露出来并且注册到注册中心,而Consumer通过注册中心获取Provider的信息,之后将自己封装成一个调用类去与Provider进行交互. 首先 ...

  2. Dubbo服务引用原理

    服务引用原理 配置文件 通过Spring容器加载 每一个标签,对应一个解析类 Reference 对应ReferenceBean 实现了FactoryBean FactoryBean 工厂Bean 引 ...

  3. Dubbo 源码分析 - 服务引用

    1. 简介 在上一篇文章中,我详细的分析了服务导出的原理.本篇文章我们趁热打铁,继续分析服务引用的原理.在 Dubbo 中,我们可以通过两种方式引用远程服务.第一种是使用服务直联的方式引用服务,第二种 ...

  4. Dubbo 服务订阅源码分析

    Dubbo 服务引用的时机有两个: 第一个是在 Spring 容器调用 ReferenceBean 的 afterPropertiesSet 方法时引用服务 第二个是在 ReferenceBean 对 ...

  5. Dubbo源码分析(六)服务引用的具体流程

    前言 在前面的章节中,我们已经完成Dubbo服务暴露的流程分析.今天我们一起来看Dubbo怎么引用这些服务的. 关于服务引用,Dubbo有两种方式.一种是基于注册中心进行服务引用,一种是服务直连进行引 ...

  6. Dubbo原理和源码解析之服务引用

    github新增仓库 "dubbo-read"(点此查看),集合所有<Dubbo原理和源码解析>系列文章,后续将继续补充该系列,同时将针对Dubbo所做的功能扩展也进行 ...

  7. (转)淘淘商城系列——引用dubbo服务

    http://blog.csdn.net/yerenyuan_pku/article/details/72758663 上文我们一起学习了如何发布一个dubbo服务,本文我就来教大家如何在web工程中 ...

  8. 分布式商城项目--dubbo 服务的发布和引用。

    分布式商城项目–dubbo 服务的发布和引用. dubbo服务需要zookeeper服务的支持,之前我们已经介绍过zookeeper的安装配置,这里就不在赘述 1.启动zookeeper 2. Pro ...

  9. Dubbo源码解析-——服务引用

    前言 在之前我们讲过Spring和Dubbo的集成,我们在服务上标注了@Reference的注解,然后最终Dubbo会调用到ReferenceBean#get方法中来返回一个代理对象,本次我们就来剖析 ...

最新文章

  1. Node.js项目实践:构建可扩展的Web应用
  2. python编码问题总结
  3. HISTORY OF ETHEREUM SECURITY VULNERABILITIES, HACKS AND THEIR FIXES
  4. 前端第一天 HTML基础
  5. 数据分析常用Python库:数值计算、可视化、机器学习等领域
  6. 1/4美国理工博士生中途离学 | Science:原因何在?
  7. vue 开发依赖安装
  8. WIN10安装VS2013出现兼容性问题解决
  9. vue v-model计算器案例
  10. 白板推导系列Pytorch-隐马尔可夫模型-概率计算问题
  11. Android使用Gson(相当于C#的Newtonsoft.Json)非常好用
  12. Hplus框架动态添加选项卡功能(扩展)
  13. 2022最新阿里Java面经,转疯了
  14. formidable词根词缀_托福词汇-重点词根词缀总结(二)
  15. 【踩坑系列】SpringBoot 项目更换浏览器选项卡的图标
  16. grasps什么意思中文_中文和日文微信名字是什么意思 163个
  17. 北京集训队2016 Day4 超级跳
  18. excel熵值法计算权重_一文讲清楚分散投资(下)——让很多人顿悟的“熵增定律”在投资中的应用...
  19. 快速刷通PWN的第一天
  20. java 弹幕 原理_Flutter 实现虎牙/斗鱼 弹幕效果

热门文章

  1. python搭建django框架,Python之Web框架Django项目搭建全过程
  2. php gbk字符串 存utf8 html,php utf8 gbk 数组 互转(示例代码)
  3. ue4 classuobject没有成员beginplay_关于UE4使用的一些想法(一)
  4. csrf攻击原理与解决方法_信息安全之CSRF攻击
  5. refreshtoken用mysql_「SpringCloud」 Spring Security OAuth2 Mysql管理在线Token
  6. 【项目管理】项目工作绩效域管理
  7. 【中间件】大数据之分布式消息队列Kafka
  8. linux安装jdk、tomcat
  9. EelemntUI中e-form表单校验的使用以及表单校验的规则
  10. Winform中使用用户控件实现带行数和标尺的RichTextBox(附代码下载)