欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Dubbo学习笔记(三)——实现原理

程序员文章站 2022-01-07 09:48:54
框架设计Dubbo的整体框架入下图所示。其中各层的说明如下:service服务层:用户编写的服务接口和服务实现类。这是框架中,唯一用户可见的。config配置层:对外的配置接口,封装配置文件中的配置信息,以 ServiceConfig, ReferenceConfig 为中心,分别表示服务提供者和消费者的配置。proxy服务代理层:用于生成服务端或者消费者的代理对象,通过代理对象来调用服务。registry注册中心层:封装服务地址的注册与发现,以服务 URL 为中心,用于服务的发现和注册。...

1.框架设计

Dubbo的整体框架入下图所示。
Dubbo学习笔记(三)——实现原理
其中各层的说明如下:

  • service服务层:用户编写的服务接口和服务实现类。是与实际业务逻辑相关的。
  • config配置层:对外的配置接口,封装配置文件中的配置信息,以 ServiceConfig, ReferenceConfig 为中心,分别表示服务提供者和消费者的配置。
  • proxy服务代理层:用于生成服务端或者消费者的代理对象,通过代理对象来调用服务。
  • registry注册中心层:封装服务地址的注册与发现,以服务 URL 为中心,用于服务的发现和注册。
  • cluster路由层:封装多个提供者的路由及负载均衡,并桥接注册中心,以 Invoker 为中心,选择调用。
  • Monitor监控层:每次的调用信息都会发送给监控层,然后由监控层进行记录RPC 调用次数和调用时间监控,以 Statistics 为中心。
  • protocol远程调用层:封装RPC调用。
  • exchange信息交换:封装请求响应模式,同步转异步。
  • transport网络传输层:抽象mina和netty为统一接口。创建客户端和服务端,建立通信连接,是真正传输的数据的地方,基于netty框架实现。
  • serialize数据序列化层:将数据进行序列化了再进行传输,传输得到的数据再反序列化。可复用一些工具。

其实大致可以分为三层:用户层、远程调用层和数据网络传输层。

2.启动解析、加载配置信息

流程如下:

  1. 容器启动。
  2. DubboNameSpaceHandler解析配置文件,并创建Dubbo标签解析器。
  3. 标签解析器挨个解析Dubbo每一个标签,每个表标签就是一个bleanclass,解析完成之后封装到每个标签指定的配置对象当中,例如ApplicationConfig、RegistryConfig…
  4. 其中Service标签对应的是 ServiceBean,Reference标签对应的是ReferenceBean,需要涉及服务暴露的问题。

3.服务暴露流程

  1. 完成ServiceBean容器创建初始化之后,由onApplicationEvent时间响应方法监听,该方法会收到Spring上下文刷新事件后执行服务导出操作。然后会触发ContextRefreshEvent事件,该事件来决定是否导出服务。
  2. ServiceConfig会调用doExportUrls来导出服务。主要做的事情就是加载注册中心连接,然后遍历每个协议进行后续的导出服务。
  3. 配置检查完毕之后,就是根据配置来组装URL。首先是将一些信息,比如版本、时间戳、方法名以及各种配置对象的字段信息放入到 map 中,map 中的内容将作为 URL 的查询字符串。构建好 map 后,紧接着是获取上下文路径、主机名以及端口号等信息。最后将 map 和主机名等数据传给 URL 构造方法创建 URL 对象。
  4. 完成了前置工作,就会创建Invoker,最后会进行服务导出,服务导出分为导出到本地和导出到远程。Invoker 是一个非常重要的模型。在服务提供端,以及服务引用端均会出现 Invoker。Dubbo 官方文档中对 Invoker 进行了说明。Invoker 是由 ProxyFactory 创建而来,Dubbo 默认的 ProxyFactory 实现类是 JavassistProxyFactory。ProxyFactory调用getInvoker创建Invoker,通过invoker的invokerMethod方法最终会调用目标方法。也会将服务信息保存到注册中心。

Invoker 是实体域,它是 Dubbo 的核心模型,其它模型都向它靠扰,或转换成它,它代表一个可执行体,可向它发起 invoke 调用,它有可能是一个本地的实现,也可能是一个远程的实现,也可能一个集群实现。

参考

4.服务引用流程

流程和上面的服务暴露流程有很多相似之处。

  1. ReferenceBean是实现了FactoryBean接口,当我们从容器中自动注入服务对象的时候,它实现其中的getObject方法,就会返回服务对象。
  2. 在引用服务时,首先对配置进行检查和处理,然后创建代理对象。
  3. 创建代理对象中,首先更具配置检查是否为本地调用,则调用 InjvmProtocol 的 refer 方法生成 InjvmInvoker 实例。若不是,则读取直连配置项,或注册中心 url,并将读取到的 url 存储到 urls 中。然后根据 urls 元素数量进行后续操作。若 urls 元素数量为1,则直接通过 Protocol 自适应拓展类构建 Invoker 实例接口。若 urls 元素数量大于1,即存在多个注册中心或服务直连 url,此时先根据 url 构建 Invoker。然后再通过 Cluster 合并多个 Invoker,最后调用 ProxyFactory 生成代理类。
  4. 创建Invoker,Invoker 是 Dubbo 的核心模型,代表一个可执行体。在服务提供方,Invoker 用于调用服务提供类。在服务消费方,Invoker 用于执行远程调用。Invoker 是由 Protocol 实现类构建而来。
  5. 其中DubboProtocol需要获取客户端进行通信,默认采用NettyClient。initClient 方法首先获取用户配置的客户端类型,默认为 netty。然后检测用户配置的客户端类型是否存在,不存在则抛出异常。最后根据 lazy 配置决定创建什么类型的客户端。这里的 LazyConnectExchangeClient 代码并不是很复杂,该类会在 request 方法被调用时通过 Exchangers 的 connect 方法创建 ExchangeClient 客户端。底层都是调用Netty创建客户端。
  6. 然后由Protocol调用refer方法引用远程服务。doRefer方法订阅服务,创建一个 RegistryDirectory 实例,然后生成服务者消费者链接,并向注册中心进行注册。注册完毕后,紧接着订阅 providers、configurators、routers 等节点下的数据。完成订阅后,RegistryDirectory 会收到这几个节点下的子节点信息。由于一个服务可能部署在多台服务器上,这样就会在 providers 产生多个节点,这个时候就需要 Cluster 将多个服务节点合并为一个,并生成一个 Invoker。
  7. 这样代理对象就创建完毕了,可以进行远程调用了。

5.服务调用流程

Dubbo服务调用的过程如图所示。

Dubbo学习笔记(三)——实现原理
上面的引用之后,产生了一个代理对象,代理对象如何调用服务。
调用链如图所示。
Dubbo学习笔记(三)——实现原理

6.其他

RPC原理

RPC的调用原理示意图如下:
Dubbo学习笔记(三)——实现原理
一次完整的RPC调用流程如下:

  1. 消费者调用以本地调用方式调用服务;
  2. client stub接收到调用后负责将方法、参数等组装成能够进行网络传输的消息体;
  3. client stub找到服务器地址,并将消息发送到服务端;
  4. server stub受到消息后进行解码;
  5. server stub根据解码结果调用本地的服务;
  6. 本地服务执行并将结果放回给server stub;
  7. server stub将返回结果打包成消息并发送给消费方;
  8. client stub接受到消息,并进行解码;
  9. 消费者得到最终的结果。

Netty通信原理

Netty是一个异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。它极大地简化了TCP和UDP套接字服务器等网络编程。

本文地址:https://blog.csdn.net/qq_36263268/article/details/111941932

相关标签: Dubbo java 网络