Great Dubbo--下

2024-03-08 14:38
文章标签 dubbo great

本文主要是介绍Great Dubbo--下,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

逻辑集群

Dubbo里两个最主要参与实体是provider和consumer,两者都是相对服务而言,前者是服务的具体实现,后者是服务的消费者。

服务在客户端被异化成提供同质的服务的逻辑集群,消费者的服务请求最终都会通过集群select出一个invoker进行远程调用,整个过程对用户是非感知的。
构建集群引用
上图是客户端引用服务的完整过程,其中主要涉及5个实体:
- Directory提供目录服务,一组invoker必定会聚集在一个目录下。它实现NotifyListener接口,监听注册中心提供者变更事件,注册中心向其推送提供者变更。目录收到的是提供者的配置信息,基于提供者配置信息客户端生成invoker,并缓存在目录里。缓存是个方法名->invoker的map结构。没有指定methods参数的则key为‘*’,代表所有方法可用,但是优先级比指定方法名的invoker低。

  • Invoker是对确定节点提供者的逻辑抽象,invoker封装了远程调用的实现细节,主要包括应用协议和传输协议等等。因为它基于提供者配置生成(配置包括但不仅限于提供者的地址和端口信息),因此它能确定指向一个节点。Invoker其实是一个边界,它是RPC协议的具体实现,这里暂且认为它是一个黑盒实体,在RPC一篇再做领域建模和细化。

  • Reference引用远端服务,它并不确定指向一个节点的提供者,而是引用由多个提供同样服务能力的invoker组成的集群。它被提供给消费者,消费者的所有请求通过它最终被委派给invoker发起remoting调用。需要说明一点,Reference并不是dubbo里的ReferenceConfig实体,而是返回给消费者的服务代理。

  • Cluster代表逻辑集群,它的背后是一组提供同质服务的节点。在dubbo里Cluster实体并不直接提供集群能力,它基于动态扩展生成特定HA策略的集群invoker,由集群invoker提供集群的相关能力。集群invoker也是一个invoker,它必定有且仅有一个目录,相应的也间接拥有0到多个invoker。
    集群invoker的结构一般如下:
    invoker进程视图

    • 消费多个注册中心的服务,最终就如上图的嵌套结构。每个注册中心生成一个集群invoker,其下包含所有注册于该中心的invoker,而最终所有这些集群invoker又都会聚集在一个大的集群invoker之下。
    • 消费单注册中心的服务,集群直接聚集invoker,此时就只会有一个集群invoker。

为了叙述方便,后文提到集群如果不做特殊说明则是指集群invoker。

  • 集群通过动态扩展点弱依赖LoadBalance,并依赖后者提供负载均衡能力,后者从集群下的所有invoker里select一个可用的,select策略可以有多种,比如加权轮询、一致性hash等等。

Reference最终按以下结构将以上实体聚合起来
Reference结构
引用和集群(非invoker)是依赖关系,前者依赖后者生成集群invoker。集群invoker和普通invoker(图里假设应用协议是dubbo)都实现了接口invoker,但前者通过目录聚集了后者的。

调用链路上,reference将请求委派给集群,集群从目录下list所有invoker再由负载均衡select,最后由被选出的invoker发起remoting,如果失败则遵循当次集群HA协议重试或者快速失败等等。
reference调用

注册中心

前面几章都或多或少提到了注册中心,注册中心是以URL流转驱动的。提供者将其配置以及地址信息通过注册中心送达到消费者,消费者再基于该配置生成对提供者的引用。理解注册中心必须首先理解URL,对URL还有疑问的可以参考上篇里的整体架构章节。

注册中心对订阅和发布的匹配是以path,以及version,group和classifier三个参数作为依据。因此提供者可以通过group和classifier提供差异化服务,消费者也可以通过这两者指定差异化服务。

zookeeper注册中心

接下来再以zookeeper注册中心举例说明一下注册中心的工作原理。
zookeeper注册中心
- 提供者export时,注册中心在zookeeper上按照/group/service/provider/url的结构写入配置信息;消费者consume时,注册中心则在zookeeper上provider节点上加上zk watcher。因此当provider节点下有写入时zookeeper就会及时将全量URL推送给注册中心,注册中心再对推送过来的URL与订阅URL进行version,group和classifier三个维度匹配,并确定是enable的服务后再推送给目录,目录会将当前所有invoker的URL信息与推送过来的URL信息做正交比较剔除重复的,对剩下的做引用。

  • Dubbo还支持消费者全量订阅,只需要配置service为“”,注册中心就会为消费者在group目录下创建zk watcher。消费者还可以通过配置category为“”全量监听服务的所有目录信息;如果想监听特定的几个目录,则只需要使用使用”,”分隔特定目录即可。

  • 一般而言zookeeper注册中心创建的都是ephemeral节点,因此在对应的写入节点offline后相应节点也会消失,因此zookeeper此时能正确推送服务下线。注册中心只是一个概念,它依赖注册中心的物理实现,而并不是有专门节点run 注册中心服务,因此注册中心的写入都是由export节点发起的。


RPC

RPC分层

RPC组件分成6层,自上而下分别是应用层,交换层,传输层,转码/序列化层、事件处理层、事件分发层。
rpc层次

Dubbo抽象出端(endpoint)的概念,端是个点,点对点之间可以进行双向传输。在此基础上扩展出通道(Channel),客户端(Client),服务端(Server)三个概念。在传输层,客户端和服务端更多体现为语义上的区别,并不区分请求和应答职责,二者拥有的都是发送能力。但客户端拥有体现其特有职责的重连能力,连接肯定都是由客户端发起,它一般是在连接超时时由心跳任务发起。客户端没有显式的连接以及断连语义,在客户端被初始化出来时就默认开启并建立与服务端连接,且通过定时任务维护通道的连接状态。因此客户端和服务端除了重连以外都只有close和send两个影响网络状态的动作。

端静态结构
服务端和客户端以通道作为传输桥梁,通道和客户端是一一对应的关系,但和服务端是多对一的关系。因为客户端和通道一对一的关系,所以在设计层面可以处理成客户端继承通道。但不管是客户端还是服务端,它们和通道的关系都体现为聚合,通过聚合的通道进行消息传输。

交换层在传输层之上扩展了请求和应答语义,体现信息交换的含义。它增加了三个实体,分别是ExchangeChannel,ExchangeClient和ExchangeServer。交换层通道增加request动作特指客户端到服务端的双向(two-way)请求,服务端到客户端均为单向应答,因此和客户端单向请求一起均使用send。交换层客户端和服务端也是点,但是有方向的点,区分明确的请求和应答职责。

客户端状态

客户端有4个动作,分别是open, connect, disconnect和close,与之相应的有5个状态,除了4个动作伴随的状态以外还有halt,客户端本身并不体现该状态,该状态只是出于对心跳超时的描述需要加入。交换层有定时任务做心跳探测,超时会发起重连。
客户端状态迁移

服务端状态相对简单很多,服务端不会主动发起连接或者断连,因此只有open和close动作,相应的也只有opened和closed两个状态。服务端也有心跳任务,心跳超时只会自动关闭server。

事件处理

ChannelHandler用于网络事件流式处理,它支持5种事件:connected,sent,received,disconnected,caught。分别对应5种网络事件:连接,发送消息,接收消息,断连和异常捕获。需要注意一点,它们对应的是网络事件,并不是端的动作或者状态,只能说端的动作会引起某个网络事件的触发,例如客户端发起connect,引起服务端connected事件。但并不是每个端动作都会触发网络事件,比如open,比如close。

处理器实现是个包装类,通过多层包装编排处理器执行顺序,对事件进行流式处理。它内聚在传输层client或者server里,在收到相应网络事件后被及时触发,并依次执行。它的执行顺序和客户端恰好相反,由下而上,自传输层到应用层。

ExchangeHandler为交换层扩展了reply语义,它并不是一种状态,只是一个动作特指服务端到客户端的应答,它发生在触发的received事件处理执行到交换层时。

下图是处理器在通用情况下的逻辑结构
handler逻辑结构
- 集合消息的接收(消息体是个list),会循环list分别委派,非集合消息或者其他类型动作直接转发,这是dubbo应用协议专用。
- 心跳时间粘连,按事件类型将读或者写事件的时间关联到channel属性,供心跳探测任务做心跳超时判断。
- 事件分发,它其实是事件分发层的具体实现,不同分发策略会使用不同的分发处理器分发事件,比如图上是默认分发策略–完全线程池分发,除此以外还有完全同步调用,只接受消息时线程池分发,除发送以外都线程池分发以及使用线程池顺序串行并有流控警告的分发方式。
- 逆序列化消息,dubbo应用协议专用。它并不是codec的具体实现,只是特定支持dubbo应用协议。
- 交换层应答语义支持,该处理实体不是交换事件处理实体,但明确是ExchangeHandler。它提供交换层的语义支持。例如服务端收到消息后即时应答,客户端收到应答唤醒pending线程返回结果以及服务端事件处理有执行异常时将异常再发送给客户端。
- 服务端应答内容处理,它是交换事件处理实体。在客户端,是ExchangeHandlerAdapter的默认实现,所有方法均为空实现;在服务端,视具体应用协议有不同交换层处理实体实现,但不论哪种实现都会保证通过serviceKey找到exporter,也就是找到本地服务,执行并返回执行结果。

RPC

再回过头来看端的静态结构,AbstractPeer是Server和Client各种具体实现的父类,它既是端又是事件处理实体,因此无论是Server还是Client它们的具体实现都有双重角色即既可以做数据传输(端的职能)又可以做事件处理(handler职能)。

RPC子域以Invoker为根,它由Protocol组件基于动态决策生成,各组件按分层结构依次聚合。交换层通道聚合传输层客户端,请求在交换层经由客户端到通道,最后又依赖传输层客户端开启传输。
rpc逻辑结构
Client会默认启动连接状态检查的定时任务,通道状态非连接时会使用新通道连接。

最后以thrift应用协议以及netty传输协议举例,描绘一下整个RPC的交互。
rpc交互
- 交换客户端将请求发送到传输层后就返回ResponseFutre,后者的get方法会进入堵塞等待,直到结果返回被唤醒。
- 事件处理实体被NettyHandler聚合,后者作为netty的网络事件处理器,在相应网络事件触发后被依次执行。比如请求发出后,以及回复抵达后等等。本节开篇说过Client的双重角色,NettyHandler持有的事件处理实体就是NettyClient本身。
- 步骤15在应答抵达后被执行,它唤醒在堵塞等待返回结果的线程,并把值以及请求状态写入返回变量中。

这篇关于Great Dubbo--下的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/787410

相关文章

Dubbo学习入门

本文参考自:Dubbo用户手册(中文)http://dubbo.apache.org/books/dubbo-user-book/ 现在的参考文档地址:http://dubbo.apache.org/zh-cn/docs/user/quick-start.html 入门请参考自《Dubbo用户手册(中文)》第一节,在手册第二节说明如何快速启动Dubbo,下面就顺着手册的使用方式,自己搭建一个快

dubbo服务过程

dubbo服务暴露过程 Dubbo通过实现ApplicationListener接口,监听了容器刷新的事件,再容器刷新后调用onApplicationEvent方法,这个是服务暴露的启动点通过识别带目标注解的服务类通过动态代理统一暴露出Invoker,如何通过配置文件以及目标协议(SPI机制)封装成exporter存储起来如果是本地注册,将exporter存入ServiceConfig的缓存,如

Dubbo缓存

是的,Dubbo 可以对服务调用结果进行缓存。通过缓存结果,可以减少重复调用、降低服务提供者的负载,并提高系统的响应速度和吞吐量。Dubbo 内置了多种缓存机制,开发者可以根据不同的业务需求选择合适的缓存策略。 1. Dubbo 结果缓存的工作原理 Dubbo 的结果缓存功能是在服务消费者一侧实现的。当一个服务消费者调用某个服务时,Dubbo 会首先检查本地缓存中是否有该服务的结果。如果缓存中

springboot+dubbo+zk 入门篇(windows单机版)

一、下载安装zk注册中心并启动:     官网地址:http://www.apache.org/dyn/closer.cgi/zookeeper/     我的是zookeeper-3.3.6版本的。下载之后需要修改下文件:进入zk的conf目录。复制下zoo_sample.cfg     这个文件并重命名为zoo.cfg,然后把修改该文件内容,下面是我的,这个只是单机配置: # 心跳时间间隔

dubbo 服务消费原理分析之引用服务配置

文章目录 前言一、服务监听ContextRefreshedEvent1、AbstractApplicationContext.refresh2、AbstractApplicationContext.finishRefresh3、DubboDeployApplicationListener.onApplicationEvent4、DefaultModuleDeployer .referServ

dubbo是什么?,能做什么?以及其工作流程

1.Dubbo是什么?能做什么? Dubbo是阿里巴巴开源的基于Java的高性能RPC分布式服务框架,现已成为Apache基金会孵化项目,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案 简单来说,dubbo就是个服务框架,如果没有分布式的需求,其实是不需要用的,只有在分布式的时候,才有dubbo这样的分布式服务框架的请求,本质上是个远程服务调用的分布式框架 其核心部

Dubbo依赖包

Dubbo 是一个高性能的 RPC 框架,用于构建分布式服务治理系统。要使用 Dubbo,项目中需要引入一些关键的依赖包。这些依赖包提供了 Dubbo 的核心功能、服务注册与发现、网络通信、序列化等能力。 一、Dubbo 核心依赖包 Dubbo 的核心依赖包包含了实现 RPC 功能的基础组件,如服务暴露、调用、负载均衡、容错机制等。以下是 Dubbo 必须依赖的核心包: 1. dubbo

zookeeper/dubbo使用记录

zookeeper版本号:zookeeper-3.4.6 在windows上使用的时候将 1,conf目录下的zoo_sample.cfg名字修改为zoo.cfg,里面内容可以不变 2,执行bin目录下的zkServer.cmd 这样zookeeper服务就启动了。 自己在本地使用zookeeper与dubbo时行接口调用时使用的时需要的部分jar包: dubbo-

dubbo之 消费者用api方式注册消费者,服务者用xml方式注册服务

场景: 我遇到的需求是:需要 服务端用xml的方式配置服务者,而消费端用api的方式配置消费者, 而官方文档只有如下三种方式,而我这种算是xml+api的方式吧(混合模式?) dubbo的实现方式有三种: 1、spirng的xml配置文件(官方文档有) 2、通过dubbo的api方式(官方文档不详细) 3、通过注解的方式。 于是不知道能不能这样搞啊,但逻辑肯定没问题嘛,因为 前后端分

Dubbo架构与底层实现

一、Dubbo的设计角色 (1)系统角色 Provider: 暴露服务的服务提供方。 Consumer: 调用远程服务的服务消费方。 Registry: 服务注册与发现的注册中心。1 Monitor: 统计服务的调用次调和调用时间的监控中心。 Container: 服务运行容器。 (2)调用关系 服务容器负责启动,加载,运行服务提供者。 服务提供者在启动时,向注册中心注册自己提供的