Dubbo 学习记录

1、Dubbo 分布式框架。 采用全 Spring 配置方式,透明化接入应用,对应用没有任何 API 侵入,只需用 Spring 加载 Dubbo 的配置即可。必须依赖JDK 1.6+。

2、Dubbo配置文件是如何加载到Spring中的?

Spring容器在启动的时候,会读取到Spring默认的一些schema以及Dubbo自定义的schema,每个schema都会对应一个自己的NamespaceHandler,NamespaceHandler里面通过BeanDefinitionParser来解析配置信息并转化为需要加载的 bean 对象!

3、Dubbo三种配置方式

Spring XML 方式,注解方式,API方式。

4、启动时检查 check

Dubbo 缺省会在启动时检查依赖的服务是否可用,不可用时会抛出异常,阻止 Spring 初始化完成,以便上线时,能及早发现问题,默认check="true"。设置为false,服务回复后会自动连上。

5、重试次数配置 retries

Dubbo 服务在尝试调用一次之后,如出现非业务异常(服务突然不可用、超时等),Dubbo 默认会进行额外的最多2次重试。可自行设置。

6、Dubbo 整体架构分层

接口服务层(Service):该层与业务逻辑相关,根据provider和consumer的业务设计对应的接口和实现

配置层(Config):对外配置接口,以ServiceConfig和ReferenceConfig为中心服务

代理层(Proxy):服务接口透明代理,生成服务的客户端Stub 和服务端的Skeleton,以ServiceProxy 为中心,扩展接口为ProxyFactory

服务注册层(Registry):封装服务地址的注册和发现,以服务URL为中心,扩展接口为RegistryFactory、Registry、RegistryService

路由层(Cluster):封装多个提供者的路由和负载均衡,并桥接注册中心,以Invoker为中心,扩展接口为Cluster、Directory、Router和LoadBlancce

监控层(Monitor):RPC调用次数和调用时间监控,以Statistics 为中心,扩展接口为MonitorFactory、Monitor和 MonitorService

远程调用层(Protocal):封装RPC调用,以Invocation和Result为中心,扩展接口为Protocal、Invoker和Exporter

信息交换层(Exchange):封装请求响应模式,同步转异步。以 Request和Response为中心,扩展接口为Exchanger、
ExchangeChannel、ExchangeClient和ExchangeServer

网络传输层(Transport):抽象mina和 netty 为统一接口,以 Message为中心,扩展接口为Channel、Transporter、Client、Server和Codec

数据序列化层(Serialize):可复用的一些工具,扩展接口为Serialization、ObjectInput、ObjectOutput和ThreadPool。

7、Dubbo 默认使用Netty 通信框架。

8、Dubbo 一般使用Zookeeper 服务注册中心。

9、Dubbo 推荐使用dubbo协议。

10、Dubbo 默认推荐使用Hessian序列化。

11、Dubbo 核心组件

  • Provider:服务的提供方
  • Consumer:调用远程服务的服务消费方
  • Registry:服务注册和发现的注册中心
  • Monitor:统计服务调用次数和调用时间的监控中心
  • Container:服务运行容器

12、 Dubbo 核心功能

Remoting:网络通信框架。

Cluster:服务框架,RPC远程过程调用,包括多协议支持,负载均衡,失败容错等。

Registry:服务注册,基于注册中心目录服务,使服务消费方能动态的查找服务提供方。

13、集群容错模式

Failover Cluster失败自动切换,当出现失败,重试其它服务器。通常用于读操作,但重试会带来更长延迟。可通过retries="2"来设置重试次数(不含第一次)。可作用于整体服务提供者,服务消费者,或单独调用方法。为Dubbo默认方式。

Failfast Cluster快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录。

Failsafe Cluster 失败安全,出现异常时,直接忽略。通常用于写入审计日志等操作。

Failback Cluster失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。

Forking Cluster并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过forks="2"来设置最大并行数。

Broadcast Cluster广播调用所有提供者,逐个调用,任意一台报错则报错。通常用于通知所有提供者更新缓存或日志等本地资源信息。

14、负载均衡

在集群负载均衡时,Dubbo 提供了多种均衡策略,默认为random随机调用。

Random LoadBalance随机,按权重设置随机概率。

RoundRobin LoadBalance轮询,按公约后的权重设置轮询比率。

LeastActive LoadBalance最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差。

ConsistentHash LoadBalance一致性 Hash,相同参数的请求总是发到同一提供者。

15、分布式服务框架(RPC)必要组件和调用过程

客户端(Client):服务调用方(服务消费者)

客户端存根(Client Stub):存放服务端地址信息,将客户端的请求参数数据信息打包成网络消息,再通过网络传输发送给服务,客户端的代理对象。

服务端存根(Server Stub):接收客户端发送过来的请求消息并进行解包,然后再调用本地服务进行处理,服务端的代理对象。

服务端(Server):服务的真正提供者

具体调用过程:

1、服务消费者(client客户端)通过调用本地服务的方式调用需要消费的服务;

2、客户端存根(client stub)接收到调用请求后负责将方法、入参等信息序列化(组装)成能够进行网络传输的消息体;

3、客户端存根(client stub)找到远程的服务地址,并且将消息通过网络发送给服务端;

4、服务端存根(server stub)收到消息后进行解码(反序列化操作);

5、服务端存根(server stub)根据解码结果调用本地的服务进行相关处理;

6、本地服务执行具体业务逻辑并将处理结果返回给服务端存根(server stub);

7、服务端存根(server stub)将返回结果重新打包成消息(序列化)并通过网络发送至消费方;

8、客户端存根(client stub)接收到消息,并进行解码(反序列化);

9、服务消费方得到最终结果。

16、本地存根 Stub

在 Dubbo 中利用本地存根在客户端执行部分逻辑。原来在服务消费端并没有针对该接口的逻辑,可以在任意地点去引用该接口,但现在加上存根配置后,需要在消费端也实现该接口并作出逻辑处理,这里并没有真正去实现服务提供者的实现逻辑,在消费者的实现里依然使用接口去调用远程实现,只是在这之外可以做出一些动作,如容错判断等。(其实我觉得好像就是:假设我想在消费端所有调这个接口前做逻辑判断,但每一个调用前都写就麻烦,即使封装也嫌麻烦,所以才搞出这个。。不知道理解对不对,感觉没必要哈哈哈!再次无语!又查了一些案例有的把存根逻辑写在接口模块中,有的写在消费者模块中,要是向官网说的写在接口模块中就说的过去了。应该都行吧,哎呀烦死了不去试了!)

17、线程模型

如果事件处理的逻辑能迅速完成,并且不会发起新的 IO 请求,比如只是在内存中记个标识,则直接在 IO 线程上处理更快,因为减少了线程池调度。

但如果事件处理逻辑较慢,或者需要发起新的 IO 请求,比如需要查询数据库,则必须派发到线程池,否则 IO 线程阻塞,将导致不能接收其它请求。

如果用 IO 线程处理事件,又在事件处理过程中发起新的 IO 请求,比如在连接事件中发起登录请求,会报“可能引发死锁”异常,但不会真死锁。

<dubbo:protocol name="dubbo" dispatcher="all" threadpool="fixed" threads="100" />

Dispatcher

  • all所有消息都派发到线程池,包括请求,响应,连接事件,断开事件,心跳等。
  • direct所有消息都不派发到线程池,全部在 IO 线程上直接执行。
  • message只有请求响应消息派发到线程池,其它连接断开事件,心跳等消息,直接在 IO 线程上执行。
  • execution只有请求消息派发到线程池,不含响应,响应和其它连接断开事件,心跳等消息,直接在 IO 线程上执行。
  • connection在 IO 线程上,将连接断开事件放入队列,有序逐个执行,其它消息派发到线程池。

ThreadPool

  • fixed固定大小线程池,启动时建立线程,不关闭,一直持有。(缺省)
  • cached缓存线程池,空闲一分钟自动删除,需要时重建。
  • limited可伸缩线程池,但池中的线程数只会增长不会收缩。只增长不收缩的目的是为了避免收缩时突然来了大流量引起的性能问题。
  • eager优先创建Worker线程池。在任务数量大于corePoolSize但是小于maximumPoolSize时,优先创建Worker来处理任务。当任务数量大于maximumPoolSize时,将任务放入阻塞队列中。阻塞队列充满时抛出RejectedExecutionException。(相比于cached:cached在任务数量超过maximumPoolSize时直接抛出异常而不是将任务放入阻塞队列)

18、只订阅禁用注册配置<dubbo:registry address=“10.20.153.10:9090” register=“false” />

19、只注册dubbo:registryid="qdRegistry"address="10.20.141.150:9090"subscribe=“false”/

20、多协议在不同服务上支持不同协议或者同一服务上同时支持多种协议。

21、多注册中心

Dubbo 支持同一服务向多注册中心同时注册,或者不同服务分别注册到不同的注册中心上去,甚至可以同时引用注册在不同注册中心上的同名服务。

22、服务分组当一个接口有多种实现时,可以用 group 区分。引用时可指定group决定使用。

23、多版本 当一个接口实现,出现不兼容升级时,可以用版本号过渡,版本号不同的服务相互间不引用。通过version 指定版本。

24、分组聚合

通过分组对结果进行聚合并返回聚合后的结果。

支持 1:搜索所有分组。2:合并指定分组。3:指定方法合并结果,其它未指定的方法,将只调用一个 Group。4:某个方法不合并结果,其它都合并结果。

25、参数验证 一般对服务端请求参数数据进行验证,这些数据一般是接口中的实体bean,对实体Bean加注解校验,并在配置中开启验证即可在请求前对数据进行基本验证。亦可扩展验证。

26、provider超时打断对于一个provider,如果某个操作执行超时,则打断(释放)该执行线程,而不是仅仅打印超时日志。

27、指定Ip Port调用Provider当多个Provider注册到注册中心时,可以通过在RpcContext中动态的指定其中一个实例的Ip,Port进行Dubbo调用。

28、结果缓存结果缓存,用于加速热门数据的访问速度,Dubbo 提供声明式缓存,以减少用户加缓存的工作量。

  • lru:基于最近最少使用原则删除多余缓存,保持最热的数据被缓存

  • threadlocal:当前线程缓存

  • jcache:可以桥接各种缓存实现

29、回声测试回声测试用于检测服务是否可用,回声测试按照正常请求流程执行,能够测试整个调用是否通畅,可用于监控。

30、上下文信息上下文中存放的是当前调用过程中所需的环境信息。

RpcContext 是一个 ThreadLocal 的临时状态记录器,当接收到 RPC 请求,或发起 RPC 请求时,RpcContext 的状态都会变化。比如:A 调 B,B 再调 C,则 B 机器上,在 B 调 C 之前,RpcContext 记录的是 A 调 B 的信息,在 B 调 C 之后,RpcContext 记录的是 B 调 C 的信息。

31、隐式参数

可以通过RpcContext上的setAttachmentgetAttachment在服务消费方和提供方之间进行参数的隐式传递。

32、异步执行

Provider端异步执行将阻塞的业务从Dubbo内部线程池切换到业务自定义线程,避免Dubbo线程池的过度占用,有助于避免不同服务间的互相影响。异步执行无异于节省资源或提升RPC响应性能,因为如果业务执行需要阻塞,则始终还是要有线程来负责执行。

Provider 端异步执行和 Consumer 端异步调用是相互独立的,你可以任意正交组合两端配置

  • Consumer同步 - Provider同步
  • Consumer异步 - Provider同步
  • Consumer同步 - Provider异步
  • Consumer异步 - Provider异步

33、异步调用基于 NIO 的非阻塞实现并行调用,客户端不需要启动多线程即可完成并行调用多个远程服务,相对多线程开销较小。

34、本地调用本地调用使用了 injvm 协议,是一个伪协议,它不开启端口,不发起远程调用,只在 JVM 内直接关联,但执行 Dubbo 的 Filter 链。

<dubbo:service protocol="injvm" />

35、参数回调参数回调方式与调用本地 callback 或 listener 相同,只需要在 Spring 的配置文件中声明哪个参数是 callback 类型即可。Dubbo 将基于长连接生成反向代理,这样就可以从服务器端调用客户端逻辑。

36、事件通知

在调用之前、调用之后、出现异常时,会触发oninvokeonreturnonthrow三个事件,可以配置当事件发生时,通知哪个类的哪个方法。

37、本地伪装 Mock 通常用于服务降级,比如某验权服务,当服务提供方全部挂掉后,客户端不抛出异常,而是通过 Mock 数据返回授权失败。Mock 是 Stub 的一个子集,便于服务提供方在客户端执行容错逻辑,因经常需要在出现 RpcException (比如网络失败,超时等)时进行容错,而在出现业务异常(比如登录用户名密码错误)时不需要容错,如果用 Stub,可能就需要捕获并依赖 RpcException 类,而用 Mock 就可以不依赖 RpcException,因为它的约定就是只有出现 RpcException 时才执行。

<dubbo:reference interface="com.foo.BarService" mock="return null" />

使用return来返回一个字符串表示的对象,作为 Mock 的返回值。合法的字符串可以是:

  • empty: 代表空,基本类型的默认值,或者集合类的空值
  • null:null
  • true:true
  • false:false
  • JSON 格式: 反序列化 JSON 所得到的对象

使用throw来返回一个 Exception 对象,作为 Mock 的返回值。

当调用出错时,抛出一个默认的 RPCException或指定异常:

<dubbo:reference interface="com.foo.BarService" mock="throw com.foo.MockException" />

force 和 fail

2.6.6以上的版本,可以开始在 Spring XML 配置文件中使用fail:force:force:代表强制使用 Mock 行为,在这种情况下不会走远程调用。fail:与默认行为一致,只有当远程调用发生错误时才使用 Mock 行为。force:fail:都支持与throw或者return组合使用。

<dubbo:reference interface="com.foo.BarService" mock="force:return fake" />

在方法级别配置 Mock

Mock 可以在方法级别上指定,假定com.foo.BarService上有好几个方法,我们可以单独为sayHello()方法指定 Mock 行为。具体配置如下所示,在本例中,只要sayHello()被调用到时,强制返回 “fake”:

<dubbo:reference id="demoService" check="false" interface="com.foo.BarService">
    <dubbo:parameter key="sayHello.mock" value="force:return fake"/>
</dubbo:reference>

38、延迟暴露

如果你的服务需要预热时间,比如初始化缓存,等待相关资源就位等,可以使用 delay 进行延迟暴露。所有服务都将在 Spring 初始化完成后进行暴露。

39、并发控制

通过对服务端或客户端进行线程控制实现,可精确到方法。<dubbo:reference>优先。也可通过负载均衡配置控制。

<dubbo:service interface="com.foo.BarService" executes="10" />

<dubbo:service interface="com.foo.BarService">
    <dubbo:method name="sayHello" executes="10" />
</dubbo:service>

<dubbo:service interface="com.foo.BarService" actives="10" />

<dubbo:reference interface="com.foo.BarService" actives="10" />

<dubbo:service interface="com.foo.BarService">
    <dubbo:method name="sayHello" actives="10" />
</dubbo:service>

<dubbo:reference interface="com.foo.BarService">
    <dubbo:method name="sayHello" actives="10" />
</dubbo:reference>

配置服务的客户端的loadbalance属性为leastactive,此 Loadbalance 会调用并发数最小的 Provider(Consumer端并发数)。

<dubbo:reference interface="com.foo.BarService" loadbalance="leastactive" />

<dubbo:service interface="com.foo.BarService" loadbalance="leastactive" />

40、连接控制

服务端连接控制限制服务器端接受的连接不能超过 10 个

<dubbo:provider protocol="dubbo" accepts="10" />

<dubbo:protocol name="dubbo" accepts="10" />

客户端连接控制限制客户端服务使用连接不能超过 10 个

<dubbo:reference interface="com.foo.BarService" connections="10" />

<dubbo:service interface="com.foo.BarService" connections="10" />

41、延迟连接

延迟连接用于减少长连接数。当有调用发起时,再创建长连接。该配置只对使用长连接的 dubbo 协议生效。

<dubbo:protocol name="dubbo" lazy="true" />

42、粘滞连接sticky

用于有状态服务,尽可能让客户端总是向同一提供者发起调用,除非该提供者挂了,再连另一台。粘滞连接将自动开启延迟连接,以减少长连接数。

<dubbo:reference id="xxxService" interface="com.xxx.XxxService" sticky="true" />

<dubbo:reference id="xxxService" interface="com.xxx.XxxService">
    <dubbo:mothod name="sayHello" sticky="true" />
</dubbo:reference>

43、令牌验证

通过令牌验证在注册中心控制权限,以决定要不要下发令牌给消费者,可以防止消费者绕过注册中心访问提供者,另外通过注册中心可灵活改变授权方式,而不需修改或升级提供者

44、路由规则

路由规则在发起一次RPC调用前起到过滤目标服务器地址的作用,过滤后的地址列表,将作为消费端最终发起RPC调用的备选地址。

  • 条件路由。支持以服务或 Consumer 应用为粒度配置路由规则。
  • 标签路由。以 Provider 应用为粒度配置路由规则。

45、配置规则

覆盖规则是 Dubbo 设计的在无需重启应用的情况下,动态调整 RPC 调用行为的一种能力。2.7.0 版本开始,支持从服务应用两个粒度来调整动态配置。

46、服务降级

可以通过服务降级功能临时屏蔽某个出错的非关键服务,并定义降级后的返回策略。

47、优雅停机

Dubbo 是通过 JDK 的 ShutdownHook 来完成优雅停机的,所以如果用户使用kill -9 PID等强制关闭指令,是不会执行优雅停机的,只有通过kill PID时,才会执行。

原理

服务提供方

  • 停止时,先标记为不接收新请求,新请求过来时直接报错,让客户端重试其它机器。
  • 然后,检测线程池中的线程是否正在运行,如果有,等待所有线程执行完成,除非超时,则强制关闭。

服务消费方

  • 停止时,不再发起新的调用请求,所有新的调用在客户端即报错。
  • 然后,检测有没有请求的响应还没有返回,等待响应返回,除非超时,则强制关闭。

48、服务容器

服务容器是一个 standalone 的启动程序,因为后台服务不需要 Tomcat 或 JBoss 等 Web 容器的功能,如果硬要用 Web 容器去加载服务提供方,增加复杂性,也浪费资源。

服务容器只是一个简单的 Main 方法,并加载一个简单的 Spring 容器(默认只加载Spring容器),用于暴露服务。

服务容器的加载内容可以扩展,内置了 spring, jetty, log4j 等加载,可进行扩展。配置配可在dubbo.properties中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值