此系列文章将会描述Java框架Spring Boot、服务治理框架Dubbo、应用容器引擎Docker,及使用Spring Boot集成Dubbo、Mybatis等开源框架,其中穿插着Spring Boot中日志切面等技术的实现,然后通过gitlab-CI以持续集成为Docker镜像。
  本文为Dubbo领域模型、调用链及调用方式

本系列文章中所使用的框架版本为Spring Boot 2.0.3-RELEASE,Spring 5.0.7-RELEASE,Dubbo 2.6.2。

Dubbo领域模型

在 Dubbo 的核心领域模型中:

  • Protocol 是服务域,它是 Invoker 暴露和引用的主功能入口,它负责 Invoker 的生命周期管理。
  • Invoker是实体域,它是Dubbo的核心模型,其它模型都向它靠扰,或转换成它,它代表一个可执行体,可向它发起invoke调用,它有可能是一个本地的实现,也可能是一个远程的实现,也可能一个集群实现。
  • Invocation 是会话域,它持有调用过程中的变量,比如方法名,参数等。

Dubbo调用链

Dubbo协议请求数据发送全调用链

  1. 由实体域(Invoker)执行会话域(Invocation)的集群实现
  2. 拦截器(Filter)链的拦截过滤
  3. 监听器(Listener)的监听指向
  4. Dubbo调用(DubboInvoker)的实现
  5. 协议头交互客户端(HeaderExchangeClient)
  6. Netty通信

Dubbo协议请求数据发送全调用链

proxy0#sayHello(String)—> InvokerInvocationHandler#invoke(Object, Method, Object[])—> MockClusterInvoker#invoke(Invocation)—> AbstractClusterInvoker#invoke(Invocation)—> FailoverClusterInvoker#doInvoke(Invocation, List<Invoker<T>>, LoadBalance)—> Filter#invoke(Invoker, Invocation)  // 包含多个 Filter 调用—> ListenerInvokerWrapper#invoke(Invocation) —> AbstractInvoker#invoke(Invocation) —> DubboInvoker#doInvoke(Invocation)    //Dubbo同异步调用—> ReferenceCountExchangeClient#request(Object, int)—> HeaderExchangeClient#request(Object, int)    //协议头交互Client—> HeaderExchangeChannel#request(Object, int)—> AbstractPeer#send(Object)—> AbstractClient#send(Object, boolean)—> NettyChannel#send(Object, boolean)   //Netty通信—> NioClientSocketChannel#write(Object)

DubboInvoker

Dubbo 的底层IO操作都是异步的。Consumer端发起调用后,得到一个Future对象。
对于同步调用,业务线程通过Future#get(timeout),阻塞等待Provider端将结果返回;timeout则是Consumer端定义的超时时间。

  • RpcInvocation设置相关参数pathversion
  • 获取ExchangeClient
  • 同步/异步调用模式
    1. 同步调用模式:框架获得DefaultFuture对象后,会立即调用get方法进行等待
    2. 异步调用模式:将该对象封装到FutureAdapter实例中,并将FutureAdapter实例设置到RpcContext中,供用户使用

FutureAdapter 是一个适配器,用于将Dubbo中的ResponseFutureJDK 中的Future进行适配。

DubboInvoker:

public class DubboInvoker<T> extends AbstractInvoker<T> {private final ExchangeClient[] clients;protected Result doInvoke(final Invocation invocation) throws Throwable {RpcInvocation inv = (RpcInvocation) invocation;final String methodName = RpcUtils.getMethodName(invocation);// 设置 path 和 version 到 attachment 中inv.setAttachment(Constants.PATH_KEY, getUrl().getPath());inv.setAttachment(Constants.VERSION_KEY, version);ExchangeClient currentClient;if (clients.length == 1) {// 从 clients 数组中获取 ExchangeClientcurrentClient = clients[0];} else {currentClient = clients[index.getAndIncrement() % clients.length];}try {// 获取异步配置boolean isAsync = RpcUtils.isAsync(getUrl(), invocation);// isOneway 为 true,表示“单向”通信boolean isOneway = RpcUtils.isOneway(getUrl(), invocation);int timeout = getUrl().getMethodParameter(methodName, Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT);// 异步无返回值if (isOneway) {boolean isSent = getUrl().getMethodParameter(methodName, Constants.SENT_KEY, false);// 发送请求currentClient.send(inv, isSent);// 设置上下文中的 future 字段为 nullRpcContext.getContext().setFuture(null);// 返回一个空的 RpcResultreturn new RpcResult();} // 异步有返回值else if (isAsync) {// 发送请求,并得到一个 ResponseFuture 实例ResponseFuture future = currentClient.request(inv, timeout);// 设置 future 到上下文中RpcContext.getContext().setFuture(new FutureAdapter<Object>(future));// 暂时返回一个空结果return new RpcResult();} // 同步调用else {RpcContext.getContext().setFuture(null);// 发送请求,得到一个 ResponseFuture 实例,并调用该实例的 get 方法进行等待return (Result) currentClient.request(inv, timeout).get();}} catch (TimeoutException e) {throw new RpcException(..., "Invoke remote method timeout....");} catch (RemotingException e) {throw new RpcException(..., "Failed to invoke remote method: ...");}}// 省略其他方法
}

Dubbo调用方式

Dubbo 缺省协议采用单一长连接,底层实现是 NettyNIO 异步通讯机制;基于这种机制,Dubbo 实现了以下几种调用方式:

  • 同步调用
  • 异步调用
  • 参数回调
  • 事件通知

下述只描述异步调用,其他调用方式详细描述及例子见Dubbo 关于同步/异步调用的几种方式

异步调用

基于Dubbo底层的异步NIO实现异步调用,对于Provider响应时间较长的场景是必须的,它能有效利用Consumer端的资源,相对于Consumer端使用多线程来说开销较小。

Provider 端接口

public interface AsyncService {String goodbye(String name);
}

Consumer 配置

<dubbo:reference id="asyncService" interface="com.alibaba.dubbo.samples.async.api.AsyncService"><dubbo:method name="goodbye" async="true"/>
</dubbo:reference>

需要异步调用的方法,均需要使用 <dubbo:method/>标签进行描述。

Consumer 端发起调用

AsyncService service = ...;
String result = service.goodbye("samples");// 这里的返回值为空,请不要使用
Future<String> future = RpcContext.getContext().getFuture();
... // 业务线程可以开始做其他事情
result = future.get(); // 阻塞需要获取异步结果时,也可以使用 get(timeout, unit) 设置超时时间

参考资料:
1.Dubbo 关于同步/异步调用的几种方式
2.服务调用过程
3.框架设计

微服务框架(十八)Dubbo领域模型、调用链及调用方式相关推荐

  1. Java 微服务框架选型(Dubbo 和 Spring Cloud?),大厂 HR 如何面试

    写在最前面,我总结出了很多互联网公司的面试题及答案,并整理成了文档,以及各种学习的进阶学习资料,免费分享给大家.扫码加微信好友进[程序员面试学习交流群],免费领取.也欢迎各位一起在群里探讨技术. 微服 ...

  2. Java 微服务框架选型(Dubbo 和 Spring Cloud?)

    |来源:博客园 |链接:https://www.cnblogs.com/xishuai/archive/2018/04/13/dubbo-and-spring-cloud.html 微服务(Micro ...

  3. Java 微服务框架选型(Dubbo 和 Spring Cloud)

    微服务(Microservices)是一种架构风格,一个大型复杂软件应用由一个或多个微服务组成.系统中的各个微服务可被独立部署,各个微服务之间是松耦合的.每个微服务仅关注于完成一件任务并很好地完成该任 ...

  4. 十分钟搭建微服务框架(SpringBoot +Dubbo+Docker+Jenkins源码)

    这套系统搭建完之后,那可就厉害了: 微服务架构 你的整个应用程序将会被拆分成一个个功能独立的子系统,独立运行,系统与系统之间通过RPC接口通信.这样这些系统之间的耦合度大大降低,你的系统将非常容易扩展 ...

  5. Java 微服务框架对比:Dubbo 和 Spring Cloud

    微服务特点: 微服务(Microservices)是一种架构风格,一个大型复杂软件应用由一个或多个微服务组成. 独立部署 松耦合 单一职责,每个服务仅关注一件任务 微服务框架 相关概念: rpc 1. ...

  6. 两大微服务框架dubbo和spring cloud对比

    一.基本介绍 dubbo Dubbo 是一个分布式服务框架,致力于提供高性能和透明化的 RPC 远程服务调用方案,以及 SOA 服务治理方案.简单的说,Dubbo 就是个服务框架,说白了就是个远程服务 ...

  7. 微服务框架-Spring Cloud简介(一)

    Spring Cloud是一个微服务框架,相比Dubbo等RPC框架, Spring Cloud提供的全套的分布式系统解决方案. Spring Cloud对微服务基础框架Netflix的多个开源组件进 ...

  8. Java 微服务框架选型

    Java 微服务框架选型(Dubbo 和 Spring Cloud?) 微服务(Microservices)是一种架构风格,一个大型复杂软件应用由一个或多个微服务组成.系统中的各个微服务可被独立部署, ...

  9. 微服务框架有哪些?如何选择?

    在微服务开发中,微服务框架通常选择 Spring Boot 和Spring Cloud,目前,国内使用较多的微服务框架主要有Dubbo和Spring Cloud,Dubbo是国内开源,在国内被使用广泛 ...

  10. 微服务架构 — 微服务框架

    目录 文章目录 目录 微服务框架 第一代微服务框架 Spring Cloud Dubbo 下一代微服务框架 - Service Mesh Istio Envoy Kubernetes + Servic ...

最新文章

  1. 华为即将发布AI新品,发力“深度学习”
  2. Centos 6.3 x86_64安装与配置bacula
  3. 收藏吧!产品再要求实现这个功能,就把这篇转给他!
  4. MyBatis ofType和javaType区别
  5. webSQL 实现即时通讯
  6. 如何查看keepalived版本号_Linux下Keepalived 安装与配置
  7. Linux yum 命令
  8. 【干货】APP产品处理加载机制和刷新机制的交互方法解析
  9. 企业为什么要开通银企直联_为什么要开通小红书企业号?——山东同乐电商培训基地...
  10. C/C++语言中联合体union的妙用
  11. QML中的JavaScript表达式
  12. 用闭包实现重载的过程学习闭包
  13. python 高维数据_用Sci-kit learn和XGBoost进行多类分类:Brainwave数据案例研究
  14. 贪心算法|Greedy Algorithms(背包问题)
  15. 英特尔云计算策略以Nehalem为主
  16. 分组取出值最大的数据
  17. 基于51单片机和 ADC0808 ADC0809的自动数字电压表proteus仿真程序设计
  18. el-select 默认选中第一个,ElementUI 下拉框
  19. html怎么隐藏项目符号,CSS-如何隐藏侧边栏列表中的项目符号?
  20. 经典的图像分割方法总结

热门文章

  1. 数美科技 | 数美科技成为无锡锡商银行首批战略合作伙伴,探索AI技术怎么样赋能普惠金融
  2. USB-Armory + Kali
  3. JVM——垃圾收集器
  4. 【机器学习项目实战】Python实现聚类(Kmeans)分析客户分组
  5. HRNet-C32-3D
  6. python奇异值分解_python scipy 奇异值分解 SVD
  7. 【Android开发】plurals 和 getQuantityString,以及%d 、%.d 、%1$s 、%1$d等的用法
  8. ARM指令集之伪指令
  9. 恶意软件实现原理解析
  10. 华为E1750上网卡往嵌入式板子上移植详解