Dubbo阅读源码带注释
系统架构解析总结
- Dubbo 框架源码最重要的设计原则是什么?从架构设计角度谈一下你对这个设计原则的理解。
- "微内核+插件"的设计模式,内核只负责组装插件(扩展点),Dubbo的功能都是由插件实现的,它的很功能点都可以被用户自定义扩展,比如:服务降级,集群容错,负载均衡等等。所以说它是一个高扩展的框架。
- 使用URL作为统一规范,用来进行数据格式来进行框架中的数据传递。
- 为什么 Dubbo 使用 URL,而不使用 JSON,使用 URL 的好处是什么?请谈一下你的看法。
- 我觉得首先是约定,那么既然是约定 有句话说的好叫约定大于配置。不管是使用JSON还是URL只要约定好就行了。其次:URL数据格式更使用Dubbo的使用场景,因为它大多数业务都是组装数据去进行这么一个RPC的通信。
-
Dubbo 官方给出了四大组件的概念,请谈一下你对它们的认识。
- Provider(服务提供者) Consumer(服务消费者) Registry(注册中心) Monitor(服务监控)
- 首先服务容器启动,服务提供者向注册中心注册并写入数据。这个过程又叫服务暴露。它做的事情主要就是将服务提供者中的主机IP,端口,以及服务名称都写入到注册中心中。然后服务消费者启动后,会向注册中心拉取服务提供者写入的数据到本地并监听订阅相关的服务,这个过程又叫服务发现。然后消费者调用提供者的时候将会被服务监控记录服务调用次数和调用耗时等等。
-
对于 Dubbo,若要了解其整个框架源码,从哪里入手比较好?
- 首先要了解它的核心动态扩展类SPI机制。
- 然后就是从xml解析开始。而xml解析就是在config这一层。
-
简述 Dubbo2.7 与 2.6 版本的区别。
- 2.7版本支持JDK8和更高的JDK版本。而2.7也是可以向下兼容的。就是我一直往前走的同时也兼容后面的版本(我觉得框架 或者说系统就应该这样,不光具有扩展性还要有兼容性的能力)。
- 其实它们最大的变化就是包名的变化,由com.alibaba.dubbo编程org.apche.dubbo。
-
什么是 SPI?请简单描述一下 SPI 要解决的问题。
-
Service Privoder Interface(服务提供者接口),是一种服务发现机制。主要解决的问题是面向抽象编程中上层对下层接口实现类的依赖问题,可以实现它们之间的解耦。
-
-
JDK 的 SPI 机制存在什么问题?
- 它会一次性加载全部的SPI接口,不管你是否需要使用,这会造成资源的浪费。
-
Dubbo 框架在设计时,为什么要将 getExtension()方法设计为实例方法?如果设计为静态方法存在什么弊端?
- getExtension()这个方法的作用是加载指定扩展名称的扩展类,而这些扩展类是配置在配置文件中的,而这些扩展名称是不能重复的。而当项目越来越大出现重复名称的可能性就很大,它这样做是为了避免这种不必要的异常。
-
Dubbo 框架的 Adaptive 类都有哪些?Adaptive 类与 Adaptive 方法的区别是什么?或者说,各自的应用场景有什么不同。
- 其为自适应机制。
- Adaptive 类有两个 AdaptiveExtensionFactory 和AdaptiveCompiler。
- Adaptive 类主要是用于限定其 SPI 扩展类的获取方式:必须按照该类中指定的方式获取Adaptive 类允许程序员在其中自行定义扩展实例的获取逻辑。
- 在获取 SPI 扩展实例时若采用自适应方式获取,系统会首先查找其 Adaptive 类,若没有找到,则会查看该 SPI 接口中的 Adaptive 方法,然后根据 Adaptive 方法自动为该 SPI 接口动态生成一个 Adaptive 扩展类,并自动将其编译。
-
Dubbo 框架的 Adaptive 方法规范中,其自动生成的 Adaptive 类名是什么格式?对Adaptive 方法有什么要求?
- 格式:XXXX$Adaptive implements SPI接口。
- 要求:必须要是URL类型的参数 或者 能从传递的参数中获取URL的信息。因为它要从URL类型的参数中取接口名。
-
Adaptive 类是否属于 SPI 直接扩展类,为什么?
- 不属于,因为它没有实现SPI接口。
- 可以说,它只是对扩展类的一种装饰。因为它并没有实现SPI接口里面的业务逻辑。它的功能就是要从现有的其它扩展类中找到一个合适它的扩展类。
SPI总结
-
简述 Dubbo 的 Wrapper 机制。
-
是对SPI接口的扩展类进行包装从而达到AOP的效果,同时也是一种设计模式。一个SPI接口可以有多个Wrapper包装机制。它不是通过注解来实现,而是通过一套Wrapper规范实现 具体规范如下:
1.Wrapper类必须实现SPI接口
2.Wrapper类中必须要有SPI接口实例构造
3.类中要有SPI接口中的方法引用
4.类名必须是以Wrapper结尾
-
-
Dubbo 的 Wrapper 类是否属于扩展类?
- 不属于直接扩展类,可以说是SPI的效果增强类。其实一种AOP思想,一个SPI接口可以有多个Wrapper扩展类 以实现不同功能的增强。
-
简述 Dubbo 的 Activae机制。
- 它是一种扩展类的激活机制,通过指定的条件来实现激活。它有三个属性:
- group: 指定激活某一个分组中的Activae实例。String[]类型,表示一个扩展类可以属于多个组。
- **value:**为当前扩展类指定的 key。String[]类型,表示一个扩展类可以属于多个组。
- **order:**指定加载顺序。
- 它是一种扩展类的激活机制,通过指定的条件来实现激活。它有三个属性:
-
Dubbo 的 Activate 类是否属于扩展类?
- 是的,Activate本身就是一种扩展。
-
请对 Dubbo 的普通扩展类、Adaptive 类、Wrapper 类,及 Activate 类的实现方式、个数,及是否属于扩展类等进行一个总结。
- **Adaptive:注解实现,用于做自适应,可用于类或方法上。类级别的配置优先于方法级别的配置。Adaptive类有两个 一是AdaptiveExtensionFactory和AdaptveCompiler。它属于SPI的扩展类(但不属于SPI的直接扩展类,因为它并没有实现SPI接口的业务逻辑)。
- **Wrapper:**类实现,用于做业务扩展,是一种AOP思想。它的实现方式是Wrapper类必须实现SPI接口,类中要有SPI的实例,类中要有SPI接口的业务引用。其个数可以有很多个,可是实现多层包装。不属于扩展类,只是一种附加属性的体现。
- **Activate:**注解实现,用于做自定义接口激活机制。可以有多个数量的激活类。是属于扩展类,其激活的功能原本就属于SPI接口。
-
简述 Dubbo 的 ExtensionLoader 实例的组成。
-
它是有 getExtensionLoader(Class type) 组成,其需要传入一个加载指定的Adaptive类。然后由ExtensionFactory创建出这个具体的扩展类并返回。
-
-
简述 Dubbo 的 ExtensionFactory 的特殊性。
- ExtensionFactory实例的作用是用于指定要加载的SPI类,它自己本身也是SPI类。
- ExtensionFactory的ExtensionLoad的ExtensionFactory的实例是null。
-
Dubbo 在查找指定扩展类时,其会查找哪些目录中的扩展类配置文件?对于这些目录中的配置文件,其是查找了所有这些目录,在一个目录中找到了就不再找其它目录了?其是仅加载了这一个扩展类还是加载了全部该 SPI 的所有扩展类?
- 会查找MEAT-INF目录下的三个目录:/dubbo/internal。/dubbo。/dubbo/service。
- 会把这三个目录全部加载并缓存到一个Map。
-
Dubbo 源码中是如何判断一个类是否是 Wrapper 类的?
-
看它是否实现了SPI接口。
-
类中是否带有一个参数为SPI接口的构造方法。
-
-
从 Dubbo 源码中可以看出,一个 SPI 接口的实现类有什么要求?
- 需要实现带有SPI注解的接口。并且类中要有这个SPI接口的无参构造器。
-
Dubbo 扩展类的功能性扩展名,除了通过扩展类配置文件指定外,还可以通过哪些方式指定?若都指定了,它们的优先级是怎样的?
- 可以通过@Extension注解指定,或者不指定。不指定的话它会默认使用类名。
- 优先级:配置文件中的扩展名,注解,默认。
-
Dubbo 会将某 SPI 接口的所有 Activate 扩展类缓存到一个 map,而 map 的 key 为其功能性扩展名,但若某个 Activate 扩展类若有多个功能性扩展名,Dubbo 是如何处理的?
- 如果某一个Activate类有多个功能性扩展名称,那么只会取第一个名称作为功能性扩展名。
IOC,APO总结
-
简述 Dubbo 中配置中心与注册中心的关系。
-
配置中心:用于完成配置信息的统一管理的。
-
注册中心:用于服务的发现和注册的。
-
如果用户没有配置配置中心,那么会将注册中心用于配置中心。
-
-
Java 类中一个标准的 Setter 有什么要求?
- 要以set开头。
- set后的首字母要大写。
- 修饰符要是public。
- 只有一个参数。
-
ExtensionLoader 实例中包含一个 ExtensionFactory 实例 objectFactory,该实例用于创建指定扩展名的扩展类实例,简述 objectFactory 创建扩展类实例的过程。
- ExtensionFactory创建的方式有两种:SPI和Spring。objectFactory创建是通过getExtension(type,name)方法先以SPI的方式寻找实例,如果找不到就已Spring的方式寻找。
-
当一个扩展类被多个 Wrapper 包装后,其自适应类实例调用的方法实际是哪个实例的方法?
- 最外层的Wrapper调用下一层Wrapper类的方法,最后一层Wrapper类调用扩展类的方法。
-
请简述一个指定功能性扩展名的扩展类实例的创建、setter 及 wrapper 的顺序与过程。
- 先加载SPI所有的扩展类到缓存(所有的四类扩展类)。然后调用getExtension获取扩展类的实例。然后调用setter方法进行注入。如果SPI接口包含了Wrapper扩展,那么就会逐个对实例进行逐个包装。
-
什么是 Javassist?
- 一个开源的动态的Java创建和编译的类库,一般情况下如果要对字节码文件进行修改,是需要使用虚拟机的指令去改的。但如果使用javassist的话就直接使用java代码的形式去改字节码文件,而不需要了解虚拟机的指令。
-
Dubbo 中对于 Adaptive 方法,系统会为其生成一个 Adaptive 类。请简述一下这个自动生成的 Adaptive 类的自动编译过程。
- 系统自动生成了Adaptive的代码。
- 然后获取到自适应编译类AdaptvieCompiler。获取到SPI注解上默认的值是javassist。加载JavassistCompiler中的compiler方法去进行编译,这个时候会把这个class加载到内存,这个时候一定会报错,因为还没有编译。它使用捕捉异常的方式调用doCompiler方法进行编译。
-
Dubbo 内核工作原理的四个构成机制间的关系是怎样的?或者说,一个扩展类实例获取过程是怎样的?
- 加载一个SPI接口,首先获取到SPI的ExtensionLoader。然后去创建该SPI接口的所有扩展类**(其为Adaptive,Wrapper,Activate,普通扩展类)**并放到缓存。
- 然后通过ExtensionLoader获取扩展类的自适应实例,去进行这个扩展类的代码生成并且进行动态编译。
- 通过自适应实例调用自适应业务方法时,才会真正去创建这个扩展类的实例。所以说 自适应实例一般都会在调用自适应业务方法时才会去创建出来。
- 然后对该实例进行注入。
- 遍历所有的Wraaper类,逐个进行包装。
标签解析/重要接口/服务发现总结
-
在 Dubbo 的 xml 配置文件的文件头中定义了 dubbo 的 xml 命名空间,并指定了当前文件所使用的 xsd 约束文件。但这个约束文件使用的是一个 http 协议的网络 url。那么,这个文件的约束真的是通过网络上的这个 xsd 文件进行约束的吗?如果是,那是通过谁进行约束的?
- 当然不是,如果是通过网络来约束的那么我电脑不连接网络的时候,那不就是约束不了了吗。它是通过一个名为dubbo.xsd的本地文件来约束dubbo的标签。而这个文件配置在spring.schemas的文件中。
-
在对 Dubbo 标签的解析中,对于没有 id 属性的标签是如何处理的?
- 如果标签中没有id属性则会取标签的name属性作为bean名称。
- 如果标签中没有name属性,而当前解析的又是Protocol(协议标签),则会直接使用dubbo作为bean名称。否则就是要interface(接口名)作为bean名称。
- 如果还是为空则使用把当前标签属性解析到的实体类名称作为bean名称**(如果当前解析的是registry标签,那就会使用registry作为bean名称)**,然后再去标签解析上下文中遍历是否存在重复的bean,如果有那就在名称后面加数字,直加到名称不重复为止。
-
请描述一下服务发布过程。
-
服务暴露:是将提供者主机的服务消息写入到zk中。
-
服务注册:将提供者服务URL暴露出来可以让消费者调用。主要完成了四项工作:形成服务暴露的URL,生成服务暴露对象Expoter,通过Netty暴露服务,同异步转换。
-
-
请描述一下 ApplicationListener 接口的作用。
- 如果一个类实现了ApplicationListener ,那它就可以监听程序的任意被动事件。被监听的类只需要继承ApplicationListener 。而目前类需要继承ApplicationEvent。触发监听的是onApplicationEvent()。
-
Dubbo 支持多注册中心,支持多服务暴露协议,请描述一下它们与服务暴露 URL的关系。
- 多注册中心:在进行暴露时,会将多个注册中心的配置信息形成一个URL。
- 多暴露协议:会逐个进行这些配置的服务协议暴露。提供者数量 * 服务协议数 = URL数。
-
Dubbo 的泛化服务、泛化引用指的是什么?
- 泛化服务:在提供者端,指的是在没有接口的情况下可以直接引用指定的实现类。
- 泛化引用:在消费者端,指的是在没有接口的情况下可以直接调用提供者端的方法。
服务订阅总结
-
简述 Consumer 的动态代理对象 Proxy 的创建过程。
- 获取到包含注册中心信息的URL。
- 将每个注册中心虚拟化成一个Invoker。根据每个注册中心UIRL构建出一个InvokerProxyFactory。
- 使用javassist为每个invoker生成一个代理对象。
-
在创建 Consumer 的动态代理对象 Proxy 过程中会将每个注册中心都虚拟化为一个Invoker,这个过程较复杂,请简述一下这个过程。
- 将当前 Consumer 注册到 zk 中,即在 zk 中创建相应的节点。
- 将 RouterFactory 的激活扩展类添加到 directory。
- 更新 Dierectory 的 Invoker 为最新的。
- 将多个 Invoker 伪装为一个 Invoker,即将 Directory 实例转换为一个 Invoker 实例。
-
在创建 Consumer 的动态代理对象 Proxy 过程中会将每个注册中心都虚拟化为一个Invoker。而在其虚拟化过程中,会将该注册中心中的所有真正的提供者 invokers 再次虚拟化为一个 invoker。从这个虚拟化过程可以看出,这个 invoker 都具有什么功能?
- 这个虚拟化过程返回的结果是一个具有服务降级功能的 MockClusterInvoker。而该Invoker 中又集成了具有集群容错功能的 Invokers 列表。集群容错的设置发生在这里。
-
每个消费者在启动时都会对 zk 中业务接口名节点下的 routers、configurators 与providers 三个 categories 节点添加 watcher 监听。请简述一下这三个节点。
-
routers:是通过 Dubbo 的管控平台动态设置的路由策略。所谓路由策略是指,什么样的消费者可以或不可以访问什么样的提供者。
-
configurators :是通过 Dubbo 的管控平台动态设置的属性配置。所谓属性配置是指,对原来在配置文件中通过 Dubbo 标签设置的属性,在这里可以进行动态更新。可以是对消费者的配置更新,也可以是对提供者的配置更新。
-
providers :其下挂着的节点就是相应服务提供者临时子节点。Invoker 列表更新,就是要读取该 providers 节点下的子节点,并将这些子节点 url 转换为 invoker。
-
-
在消费者获取 Invoker 过程中大量出现了将多个 invoker 伪装为一个 Invoker 的情况,为什么要这样设计呢?
- 主要是为了应用服务路由、负载均衡、集群容错机制。即可以根据需求选择需要的Invoker。
- 然后服务路由楚的Invoker进行负载均衡。然后对负载出的Invoker进行调用。如果调用出现问题就是要对应设置的容错机制进行容错。
远程调用总结
- Consumer 发出一个远程调用后,就服务路由、服务降级、集群容错、负载均衡这四个过程,是如何执行的,或者说是怎样的一个执行顺序?
- 在Consumer发出一个远程调用请求后,首先会根据服务降级的设置进行降级业务。
- 如果能走到服务路由这一步,会通过路由过滤掉一些配置的Invoker。
- 然后再去对这些Invoker进行负载均衡选出一个Invoker进行调用。
- 如果调用的过程中出现了错误,则再根据具体配置的容错楚策略进行容错。
-
集群容错策略是在何时设置到远程调用过程的?
- 在消费者启动的时候就设置到每个注册中心中的Inovkers中虚拟楚的Invoker中了。
-
负载均衡策略是在何时设置到远程调用过程的?
- 首先远程调用的第一关是服务降级。
- 如果过了服务降级接下来就是路由,根据路由条件会过滤掉一部分Invoker。
- 然后对路由过后的Invoker再进行负载均衡。
-
Consumer 在进行远程调用时,其代码中获取到的是一个什么类型的结果?请对这个结果进行一些简单描述。
- 获取到的是一个异步结果,会将这个异步结果交给线程池中作为一个任务去处理,并且为这个任务添加了一个监听器。
-
请总结一下消费者端的“同步转异步”过程。
- 消费者端同步转异步就是 ExchangeClient 通过 NettyClient 提交一个异步的远程调用请求。
- 在 ExchangeClient 之前,远程调用请求是以同步方式执行的。而同步调用发出异步请求,则是通过 ExchangeClient 发出的。所以,ExchangeClient 实现了“同步转异步”。
-
一个消费者在使用 Dubbo 协议进行服务消费时,其能够创建多少个长连接?
- 默认是一个物理长连接,可以通过系统变量或属性文件dubbo:Consumer 标签 shareConnections属性 来指定可以最多共享多少个逻辑连接。既物理连接可以同事为多个请求服务。
- 也可以通过在dubbo:Consumer dubbo:reference 中设置connection属性来指定可以最多开启多少个物理连接,但是该物理连接是不可以共享的。
-
无论是物理连接,还是逻辑连接,系统都会为其创建并绑定一个同步转异步实例ExchangeClient,但这个实例的类型是不相同的。请简单说一下有什么不同?
- 不管是逻辑连接还是物理连接,系统都会为它们创建一个同步转异步实例的ExchangeClinet。而它们之间不同的是,逻辑连接中的ExchangeClinet中会有一个共享计数器。
-
请简述一下消费者端的连接、ExchangeClient 及 Netty Client 的关系
-
一个消费者在与提供者通信的时候,系统都会创建多个连接,每个连接不管是物理连接还是逻辑连接,都会产生出一个ExchangeClinet。
-
而一个ExchangeClinet又会创建一个对应的NettyClinet。它们的关系是:
消费者与连接:1/n
连接与ExchangeClinet:1/1
ExchangeClinet与NettyClinet:1/1
-
如果一个消费者有多个连接,那么就会创建多个NettyClinet客户端。
-
路由/降级/容错总结
- 简述什么是服务路由?
-
简单的说就是以一些规则语法来配置让消费者不去访问对应的提供者。如指定服务IP黑名单,指定访问某一个提供者,或指定不访问指定的提供者。
-
它提供了三种路由方式。脚本路由,条件路由,标签路由。
-
在进行RPC调用之前会将符合配置条件的Invoker过滤掉。
-
Dubbo 中在进行路由过滤时,若提供者不满足路由规则,则该提供者将被踢除。但若消费者不符合路由规则,系统是如何处理的呢?
- 如果消费者不符合规则,那就直接返回所有的invoker。
-
简述 Dubbo 中常见的服务降级设置。
- mock="force:return null" 强制降级,不会进行调用。
- mock="fail:return null" 在调用提供者方法失败后,再进行服务降级。不会抛异常。
- mock="true" 在调用提供者方法失败后,使用消费者方Mock 类实例的相应方法。而该 Mock 类的类名为“业务接口名+Mock”,且放在与接口相同的包中。
- mock="降级的全限定类名" 和 **mock="true"**类似,但是不需要指定以Mock为类名称的结尾。可自定义类名称
-
Dubbo 中对于自定义的服务降级处理类有两种,都各有什么要求呢?请谈一下你的认识。
- 第一种是设置 mock="true" 这种方式,这种方式的话需要把降级类放在消费者业务包下,并且降级类名要以Mock结尾。
- 第二种是设置 mock="降级的全限定类名" 这种方式,这种方式的话对包路径和类名称没有要求。
-
简述 Dubbo 中集群容错与服务降级的区别与联系。
- 降级在容错之后,集群容错在降级之前。因为只有在集群容错正在的存在意义是以一种怎样的方式来处理消费者调用提供者失败的这种情况。
-
请总结一下 Dubbo 集群容错策略中哪些可能引发降级处理,哪些不会。
-
记住了,只要集群容错策略处理业务中。抛出RpcException的就会进行服务降级。否则就不会。
-
-
Dubbo 集群容错策略中的 Failback 策略在调用失败后会发起定时重试,这个定时任务仅会执行一次,还是可以无限重试下去直至成功或超时?
- 是通过用户通过retries属性设置的。
-
Dubbo集群容错策略中的 Forking策略在配置文件中通过 forks属性指定分叉数量时,是否需要考虑提供者的数量?
-
简单的说不需要考虑提供者数量。因为如果forks分支 大于 提供者,那么forks的数量就 等于 提供者数量。如果 小于 提供者数量,那么forks分支数就是 forks分指数。简单的说是forks占据的主动权。
-
-
对比一下 Dubbo 集群容错策略中的 Forking 策略与 Broadcast 策略的异同点。
-
Forking :只需要一个分支返回了结果就返回结果。
-
**Broadcast :**需要每一个分支的结果,只要有一个结果是异常就抛异常。
-
负载均衡总结
-
Dubbo 的负载均衡是如何实现的?
-
在RPC调用之前会默认或根据用户配置对提供者集群节点进行负载,负载均衡算法有四种,其四种算法中都包含了加权 :
**1.随机(服务级别):**从集群节点中随机选出一个节点进行RPC调用。
2.**最小活跃度(服务级别):**性能强的服务器往往会被分配较多的请求,就是谁处理的快,处理完又会被分配新的请求。能力越大,责任越大。
3.**轮询(方法级别):**对已有的可用的集群节点进行轮询调用。
4.**一致性Hash(方法参数级别):**将一样参数的请求都分配到一个节点上,将缓存应用极致,以提高性能。
-
-
Dubbo 的负载均衡策略是何时获取到的?
- 在RPC远程调用之前,在服务路由过滤掉不可用的Invoker之后。就会从URL配置中获取用户配置的负载均衡策略。如果配置不到就会默认使用随机负载均衡策略。
-
Dubbo 的负载均衡发生之前,首先会判断消费者是否开启了粘连连接功能。什么是粘连连接?
- 简单的说就是缓存,它是由用户使用 sticky=true 来设置开启的。目的就是为了让消费者尽量调用同一个服务提供者以来提高性能。
-
Dubbo 的 FailoverClusterInvoker 的 doInvoke()方法中有一个集合 selected,请简述该集合的作用。
-
这个集合是记录负载过的节点,每一次负载选择出的节点都会被记录下到这个集合,然后下载进行负载的时候就会把这个集合中的节点都排除掉然后再进行负载。
-
-
Dubbo 中的负载均衡内部在选择出一个 invoker 后会对其进行可用性检测。若检测结果为不可用怎么办?
- 则进行下一次选择,源码里面是直接 continue; 了
-
简述 Dubbo 的加权随机算法思想。
- 其加权算法的核心思想是: 每个服务启动的时候都需要时间,我们称这个时间为预热 同时 用户也可以自定义设置指定服务的服务预热时间。其设置属性为warmup="60000" 单位为毫秒。 是为了让刚刚启动的服务尽量处理少一点的请求,避免服务刚刚启动就被随机轮询分配太多的请求从而打垮服务。
-
Dubbo 中为提供者设置的权重是否可以指定为负数?
- 可以,但是如果设置为负数那该服务就永远不会接收到请求。
-
什么是 Dubbo 的预热权重?
-
是在服务启动的时候给予服务分配少一点的请求,然随着时间的推移最终预热时间达到后。权重最终会变成用户真正设置的权重。
-
-
简述 Dubbo 的加权最小活跃度调度算法思想。
-
随着服务节点运行了一段时间后,就越来越能看出这些服务节点的处理性能。而性能好的节点处理请求就快一点,活跃度就少一点。
而那些服务性能不好的节点,活跃度就高一点。
-
这样,性能好的就会被多分配一些请求,反之性能不是很好的服务节点就少分配一点请求 。
-
总结起来就是,能力越大 责任越大。
-
-
简述 Dubbo 的双权重轮询算法思想。
-
双重轮询 指的是主机权重和轮询权重。它是用主机权重减去轮询权重。选出最大的那个Invoker去进行RPC调用。
-
-
简述 Dubbo 内置负载均衡算法的应用场景。
-
**随机算法:**用于服务级别,其适用于,提供者主机性能差别较大的场景。若所有提供者的性能差别不大,则会使该算法变为了纯粹的随机算法。而纯粹的随机算法则可能会出现“负载堆积”问题,即可能存在生成的某些随机数机率较高从而导致某些提供者的负载较大。
-
**最小活跃度:**用于服务级别,其适合于提供者主机性能差别不大的场景。根据各个提供者主机当前处理实际情况进行负载均衡。某一台机器处理的请求快,处理完了就又会给这个机器分请求处理。 似于:能力越大 责任越大。
-
**轮询算法:**用于方法级别,其适用于当有那些非常耗时的业务时,可针对这个业务方法指定使用轮询算法。因为如果这种业务使用随机算法的话,当出现高并发的时候就会直接把这个服务节点直接打瘫痪。如果能使用轮询算法针对一个服务方法做负载,则可以避免这种问题。
-
**一致性Hash:**用于方法参数级别,需要能指定参数个数方法,这样的话能将Invoker缓存用到极致,提高调用性能。
-