dubbo

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq541005640/article/details/81487355

目录

dubbo是什么?

dubbo的架构

节点角色说明

调用关系说明

连通性

健壮性

伸缩性

dubbo默认使用什么通信协议?

Dubbo超时重试机制带来的数据重复问题

dubbo连接注册中心和直连的区别

Dubbo在安全机制方面是如何解决的 

一般使用什么注册中心,还有其他的选择吗?

服务提供者能实现失效踢出的原理

持久节点

临时节点

应用场景

服务上线怎么不影响旧版本(多版本支持)

dubbo协议下的单一长连接与多线程并发如何协同工作

集群容错怎么做 

dubbo是如何实现负载均衡

遇到的问题


dubbo是什么?

dubbo是一个分布式框架,远程服务调用的分布式框架

dubbo能做什么?

  1. 透明化的远程方法调用,就像调用本地方法一样调用远程方法,只需简单配置,没有任何API侵入。
  2. 软负载均衡及容错机制,可在内网替代F5等硬件负载均衡器,降低成本,减少单点。
  3. 服务自动注册与发现,不再需要写死服务提供方地址,注册中心基于接口名查询服务提供者的IP地址,并且能够平滑添加或删除服务提供者。

dubbo的架构

节点角色说明

  1. Provider: 暴露服务的服务提供方。
  2. Consumer: 调用远程服务的服务消费方。
  3. Registry: 服务注册与发现的注册中心。
  4. Monitor: 统计服务的调用次调和调用时间的监控中心。
  5. Container: 服务运行容器。

调用关系说明

0.服务容器负责启动,加载,运行服务提供者。

1.服务提供者在启动时,向注册中心注册自己提供的服务。

2.服务消费者在启动时,向注册中心订阅自己所需的服务。

3.注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。

4.服务消费者,从提供者地址列表中,基于软负载均衡算法(负载均衡算法包括轮询法、随机法、最少活跃调用数、一致性Hash等),选一台提供者进行调用,如果调用失败,再选另一台调用。

5.服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。

Dubbo 架构具有以下几个特点,分别是连通性、健壮性、伸缩性、以及向未来架构的升级性。

连通性

  1. 注册中心负责服务地址的注册与查找,相当于目录服务,服务提供者和消费者只在启动时与注册中心交互,注册中心不转发请求,压力较小
  2. 监控中心负责统计各服务调用次数,调用时间等,统计先在内存汇总后每分钟一次发送到监控中心服务器,并以报表展示
  3. 服务提供者向注册中心注册其提供的服务,并汇报调用时间到监控中心,此时间不包含网络开销
  4. 服务消费者向注册中心获取服务提供者地址列表,并根据负载算法直接调用提供者,同时汇报调用时间到监控中心,此时间包含网络开销
  5. 注册中心,服务提供者,服务消费者三者之间均为长连接监控中心除外
  6. 注册中心通过长连接感知服务提供者的存在,服务提供者宕机,注册中心将立即推送事件通知消费者
  7. 注册中心和监控中心全部宕机,不影响已运行的提供者和消费者,消费者在本地缓存了提供者列表
  8. 注册中心和监控中心都是可选的,服务消费者可以直连服务提供者

 

健壮性

  1. 监控中心宕掉不影响使用,只是丢失部分采样数据
  2. 数据库宕掉后,注册中心仍能通过缓存提供服务列表查询,但不能注册新服务
  3. 注册中心对等集群,任意一台宕掉后,将自动切换到另一台
  4. 注册中心全部宕掉后,服务提供者和服务消费者仍能通过本地缓存通讯
  5. 服务提供者无状态,任意一台宕掉后,不影响使用
  6. 服务提供者全部宕掉后,服务消费者应用将无法使用,并无限次重连等待服务提供者恢复

 

伸缩性

  1. 注册中心为对等集群,可动态增加机器部署实例,所有客户端将自动发现新的注册中心
  2. 服务提供者无状态,可动态增加机器部署实例,注册中心将推送新的服务提供者信息给消费者

 

dubbo默认使用什么通信协议?

dubbo共支持如下几种通信协议:

  • dubbo: 单一长连接和NIO异步通讯,适合大并发小数据量的服务调用,以及消费者远大于提供者。传输协议TCP,异步,Hessian序列化;
  • rmi: 采用JDK标准的rmi协议实现,传输参数和返回参数对象需要实现Serializable接口,使用java标准序列化机制,使用阻塞式短连接,传输数据包大小混合,消费者和提供者个数差不多,可传文件,传输协议TCP。 多个短连接,TCP协议传输,同步传输,适用常规的远程服务调用和rmi互操作。在依赖低版本的Common-Collections包,java序列化存在安全漏洞;
  • webservice: 基于WebService的远程调用协议,集成CXF实现,提供和原生WebService的互操作。多个短连接,基于HTTP传输,同步传输,适用系统集成和跨语言调用;
  • http: 基于Http表单提交的远程调用协议,使用Spring的HttpInvoke实现。多个短连接,传输协议HTTP,传入参数大小混合,提供者个数多于消费者,需要给应用程序和浏览器JS调用;
  • hessian: 集成Hessian服务,基于HTTP通讯,采用Servlet暴露服务,Dubbo内嵌Jetty作为服务器时默认实现,提供与Hession服务互操作。多个短连接,同步HTTP传输,Hessian序列化,传入参数较大,提供者大于消费者,提供者压力较大,可传文件;
  • memcache: 基于memcached实现的RPC协议
  • redis: 基于redis实现的RPC协议

 

Dubbo超时重试机制带来的数据重复问题

Dubbo的超时重试机制为服务容错、服务稳定提供了比较好的框架支持,但是在一些比较特殊的网络环境下(网络传输慢,并发多)可能由于服务响应慢,Dubbo自身的超时重试机制(服务端的处理时间超过了设定的超时时间时,就会有重复请求)可能会带来一些麻烦。


常见的应用场景故障:  1、发送邮件(重复) ;2、账户注册(重复)。

解决方案:         
    1.对于核心的服务中心,去除dubbo超时重试机制,并重新评估设置超时时间。         

          (1)、去掉超时重试机制  

<dubbo:provider delay="-1" timeout="6000"  retries="0"/> 

 (2)、重新评估设置超时时间

 <dubbo:service interface="*.*" ref="*"  timeout="延长服务时间"/>

2.业务处理代码必须放在服务端,客户端只做参数验证和服务调用,不涉及业务流程处理。

 

dubbo连接注册中心和直连的区别

1)直连方式

     在开发及测试环境下,经常需要绕过注册中心,只测试指定服务提供者,这时候可能需要点对点直连, 点对点直联方式,将以服务接口为单位,忽略注册中心的提供者列表

2)注册中心方式

     而服务注册中心,动态的注册和发现服务,使服务的位置透明,并通过在消费方获取服务提供方地址列表,实现软负载均衡和Failover, 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。

Dubbo在安全机制方面是如何解决的 

Dubbo通过Token令牌防止用户绕过注册中心直连,然后在注册中心上管理授权。Dubbo还提供服务黑白名单,来控制服务所允许的调用方

一般使用什么注册中心,还有其他的选择吗?

 Multicast注册中心
 Zookeeper注册中心
 Redis注册中心
 Simple注册中心

1、当服务提供者启动时,Zookeeper向/dubbo/com.foo.BarService/providers目录下写入服务提供者的URL地址。

2、当服务消费者启动时,这时候有两个动作:

订阅/dubbo/com.foo.BarService/providers目录下的服务提供者URL地址。
并向/dubbo/com.foo.BarService/consumers目录下写入服务消费者的URL地址。

3、当监控中心启动时,订阅/dubbo/com.foo.BarService目录下的所有提供者和消费者URL地址。

 

服务提供者能实现失效踢出的原理

服务失效踢出是基于Zookeeper的临时节点原理。

zookeeper中节点是有生命周期的.具体的生命周期取决于节点的类型.节点主要分为持久节点(Persistent)临时节点(Ephemeral),但是更详细的话还可以加上时序节点(Sequential),创建节点中往往组合使用,因此也就是4种.

  • 持久节点
  • 持久顺序节点
  • 临时节点
  • 临时顺序节点

其实不要纠结于分为几种,这就和语文的断句一样,你断句的方法不同,断出来的结果也不同.那么我们主要讲讲持久节点临时节点的区别

持久节点

所谓持久节点,是指在节点创建后,就一直存在,直到有删除操作来主动清除这个节点,也就是说不会因为创建该节点的客户端会话失效而消失

临时节点

临时节点的生命周期和客户端会话绑定,也就是说,如果客户端会话失效,那么这个节点就会自动被清除掉

应用场景

在分布式系统中,我们常常需要知道某个机器是否可用,传统的开发中,可以通过Ping某个主机来实现,Ping得通说明对方是可用的,相反是不可用的,ZK 中我们让所有的机器都注册一个临时节点,我们判断一个机器是否可用,我们只需要判断这个节点在ZK中是否存在就可以了,不需要直接去连接需要检查的机器,降低系统的复杂度

 

服务上线怎么不影响旧版本(多版本支持)

dubbo的文档中说到:

当一个接口实现,出现不兼容升级时,可以用版本号过渡,版本号不同的服务相互间不引用。
 在低压力时间段,先升级一半提供者为新版本,再将所有消费者升级为新版本,然后将剩下的一半提供者升级为新版本
<dubbo:service interface="com.foo.BarService" version="1.0.0" />
<dubbo:service interface="com.foo.BarService" version="2.0.0" />
<dubbo:reference id="barService" interface="com.foo.BarService" version="1.0.0" />
<dubbo:reference id="barService" interface="com.foo.BarService" version="2.0.0" />
不区分版本:(2.2.0以上版本支持)
<dubbo:reference id="barService" interface="com.foo.BarService" version="*" />

dubbo协议下的单一长连接与多线程并发如何协同工作

底层采用netty。

集群容错怎么做 

当我们的系统中用到Dubbo的集群环境,因为各种原因在集群调用失败时,Dubbo提供了多种容错方案,缺省为failover重试。
集群容错模式:
1、Failover Cluster
      失败自动切换,当出现失败,重试其它服务器。(缺省)
      通常用于读操作,但重试会带来更长延迟。
      可通过retries="2"来设置重试次数(不含第一次)。正是文章刚开始说的那种情况.
2、Failfast Cluster
      快速失败,只发起一次调用,失败立即报错。
      通常用于非幂等性的写操作,比如新增记录。
3、Failsafe Cluster
      失败安全,出现异常时,直接忽略。
      通常用于写入审计日志等操作。
4、Failback Cluster
      失败自动恢复,后台记录失败请求,定时重发。
      通常用于消息通知操作。
5、Forking Cluster
      并行调用多个服务器,只要一个成功即返回。
      通常用于实时性要求较高的读操作,但需要浪费更多服务资源。
      可通过forks="2"来设置最大并行数。
6、Broadcast Cluster
      广播调用所有提供者,逐个调用,任意一台报错则报错。(2.1.0开始支持)
      通常用于通知所有提供者更新缓存或日志等本地资源信息。


重试次数配置如:(failover集群模式生效)

<dubbo:service retries="2"/>
或:
<dubbo:reference retries="2"/>
或:
<dubbo:reference>
<dubbo:methodname="findFoo"retries="2"/>
</dubbo:reference>

集群模式配置如:

<dubbo:servicecluster="failsafe"/>
或:<dubbo:referencecluster="failsafe"/>

dubbo是如何实现负载均衡

dubbo负载均衡策略:
在集群负载均衡时,Dubbo提供了多种均衡策略,缺省为random随机调用。
1、Random  LoadBalance
      随机,按权重设置随机概率。
      在一个截面上碰撞的概率高,但调用量越大分布越均匀,而且按概率使用权重后也比较均匀,有利于动态调整提供者权重。
2、RoundRobin  LoadBalance
      轮循,按公约后的权重设置轮循比率。
      存在慢的提供者累积请求问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上。
3、LeastActive  LoadBalance
      最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差。
      使慢的提供者收到更少请求,因为越慢的提供者的调用前后计数差会越大。
4、ConsistentHash  LoadBalance
      一致性Hash,相同参数的请求总是发到同一提供者。
      当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。


Dubbo的集群容错和负载均衡同样也是Dubbo本身的高级特性。正如我们在说自定义扩展的时候一样,这两个特征同样也可以进行自定义扩展,用户可以根据自己实际的需求来扩展他们从而满足项目的实际需求.

遇到的问题

场景描述:客户端远程异步调用ServiceA,ServiceA在处理客户端请求的过程中需要远程同步调用ServiceB,ServiceA从ServiceB的响应中取数据时,得到的是null。
对于上面的问题,解决办法有三个:
1.方法调用两次

ServiceA调用ServiceB的地方写两次一样的调用,这个方法原理就像ServiceB调用ServiceC一样,即清除attachements。
这个方法最简单,但是可能对不了解的人来说,这块业务代码写重复了,会不小心删除掉,而且从写代码的角度来说,这个很鸡肋,所以不推荐。
 

2.修改Dubbo源码

 修改AbstractInvoker第137行,改成每次都对async进行实际赋值,
 boolean isAsync = getUrl().getMethodParameter(invocation.getMethodName(), Constants.ASYNC_KEY, false);
 invocation.setAttachment(Constants.ASYNC_KEY, String.valueOf(isAsync));
 

3.自定义Filter

 实现com.alibaba.dubbo.rpc.Filter,在RpcContext中清除这个async,
 @Activate(group = {Constants.PROVIDER})
  public class AsyncFilter implements Filter {
 @Override
 public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
     RpcContext.getContext().getAttachments().remove(Constants.ASYNC_KEY);
 return invoker.invoke(invocation);
 }
 }
 同时在src/main/resources/META-INF/dubbo/下添加com.alibaba.dubbo.rpc.Filter文件,内容文件如下:
 asyncFilter=com.abc.filter.AsyncFilter

根据n多的博客整理出来的一些,以后有其他东西再加进去

转载地址:https://www.jianshu.com/p/9d062eceb765

展开阅读全文

没有更多推荐了,返回首页