avatar

41.Dubbo的服务治理功能

上篇简单对Dubbo入了个门,接下来我们来看看Dubbo服务治理的功能,这篇我们主要会说到:

  1. dubbo的负载均衡
  2. dubbo的集群容错
  3. dubbo的服务降级

0x01 dubbo的负载均衡

  1. dubbo为什么需要负载均衡?
    • 当服务端存在多个节点时,在我们的注册中心上就会维护不同服务节点,而对于客户端来说,他仅仅只需要一个节点去调用就行了,那么到底选哪一台呢?这时候就需要一种负载均衡机制来选择一台节点来进行调用。通过负载均衡,可以让每个服务节点获得适合自己处理能力的负载。
    • 负载均衡一般分为两大类,一个是软件实现负载均衡(软负载)如Nginx,一种就是由硬件进行实现负载均衡,如F5。而在Dubbo中是采用软负载,在Dubbo中集成了负载均衡算法的实现,默认提供了4种负载均衡算法。
  2. 如何配置Dubbo的负载均衡?`
    1. 在服务端的dubbo:service标签中使用loadbalance配置。取值为:roundrobin/random/leastactive/consistenthash其中之一。例如:
      • <dubbo:service interface="xxx" loadbalance="random" />
    2. 在客户端的dubbo:reference标签中使用loadbalance配置。取值同上。例如:
      • <dubbo:reference interface="xxx" loadbalance="roundrobin">
    3. 如果是基于注解,则可以在服务端的@Service注解中配置loadbalance。如:@Service(loadbalance="random"),也可以在消费端的@Renference注解中配置loadbalance。如:@Reference(loadbalance = "random")
    4. 注意:负载均衡实现是在消费端,也就是说如果在服务端配置了,同时也在消费端配置了,最终是以消费端为准。
  3. Dubbo中负载均衡算法
    • RandomLoadBalance
      • 权重随机算法,根据权重值进行随机负载。配置值:random,是dubbo默认采用的算法。
      • 算法思想:
        • 假设有几个服务器节点A,B,C.我们给他们的权重是2,6,9。
        • 算出他们的总和,也就是2+6+9=17。
        • 在0~17之内找一个随机数。假设找到了5.
        • 然后在坐标上把权重平铺下,也就是[0,2)属于A,[2,8)属于B,[8,17)属于C。
        • 那么我们取到了随机数5,5在[2,8)区间,所以这次请求会到B服务器上执行。
      • 从算法思想上可以看到,权重越大,区间跨度也就越大,那么请求落到这个区间的概率也就越大。
      • 那么他是怎么实现这个算法的呢?稍微透露下,具体在后面分析消费端源码时说。
        • 首先上面在0~17内找到一个随机数,是5.
        • 那么他会用5减去这3个权重,一直到该数值<0.例如。他会先用5-2=3,这时候是>0的,所以继续往下减,也就是用3-6=-3这时候结果是<0的,就不继续再减了,就取6所对应的服务器节点。
        • 通过这种方式来实现取到的随机数落在哪个区间。
    • LeastActiveLoadBalance
      • 最小活跃调用数算法,活跃调用数越小,表名该服务提供者效率越高,单位时间内可处理的请求也就越多。这是比较科学的负载均衡算法。配置值是:leastactive
      • 算法思想:
        • 每个服务提供者都会有个活跃数active。在默认情况下为0。
        • 每当来一个请求,该值会+1.每当完成一个请求时,该值会-1.
        • 所以在服务运行到一定时间后,性能好的服务器处理请求的速度更快,因此该值下降的也越快,此时这样的服务节点可以优先获取到新的请求。
    • ConsistentHashLoadBalance
      • hash一致性算法。配置值为:consistenthash
      • 算法思想:
        • 相同参数的请求总是会来到同一个服务提供者节点。
        • 当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。
    • RoundRobinLoadBalance
      • 加权轮询算法,配置值为:roundrobin
      • 算法思想:
        • 本质上是在轮询算法的基础上加上权重。那么什么是轮询算法呢?说白点,就是你一次我一次他一次。一人一次轮着来,这就是轮询。
        • 加权轮询是对轮询的过程进行加权。比如服务器A,B,C的权重比为5:3:2。那么在10次请求中,A服务器会接收5次请求,B服务器会接收3次,C服务器会接受2次。
      • 轮询算法适用于服务器性能相近的场景,而加权轮询会以权重的方式来调控每台服务器的负载,在经过加权后,每台服务器能搞得到的请求数比例,接近或等于他们的权重比。

0x02 dubbo的集群容错

  1. 什么是容错?
    • 从字面上看,容就是容忍,错就是错误,连起来就是容忍错误的能力。
    • 我们知道在网络上有很多不确定因素,比如延迟,服务提供者宕机了,服务中断了等,会造成本次服务调用失败。当服务通信出现这些问题时,就需要采取一些措施来应对,在Dubbo中提供了容错机制来处理这种错误。
  2. dubbo的容错机制的配置
    • 使用xml方式配置:在服务提供方的<dubbo:service>标签中配置cluster属性。例如:
      • <dubbo:service interface="xxxx" cluster="容错方案" />
    • 使用Spring Config方式配置:在@Service注解中配置cluster属性。例如:
      • @Service(cluster="容错方案")
  3. dubbo的容错机制(不限于下面这几种,详见Dubbo集群)
    • Failover Cluster(默认)
      • 失败自动切换,即当出现失败时,重试调用其他服务器。可以通过配置retries来设置重试次数。当retries设置为3时,会重试3次。总共会执行4次。通常用于读操作。
      • 配置值:failover
    • Failfast Cluster
      • 快速失败,只发起一次调用,如果出错就会报错(抛异常),不会再去调用。通常用于幂等性的操作,比如新增记录。
      • 配置值:failfast
    • Failsafe Cluster
      • 失败安全,出现异常时,仅仅打印异常,不会抛出,通常用于写入审计日志等操作。
      • 配置值:failsafe
    • Failback Cluster
      • 失败自动恢复,后台记录失败请求,定时去重试,通常用于消息通知操作
      • 配置值:failback
    • Forking Cluster
      • 并行调用多个服务器,只要一个成功就返回。通常用于实时性要求较高的读操作,但这样会浪费很多服务器资源。可通过forks来配置最大并行数。
      • 配置值:forking
    • Broadcast Cluster
      • 逐个调用每个服务提供者,如果其中一台报错,在循环调用结束后,会抛出异常。常用于通知所有提供者更新缓存或日志等本地资源信息。
      • 配置值:broadcast
  4. 在实际应用中,查询语句容错策略建议使用默认Failover Cluster,而增删改建议使用Failfast Cluster或者使用Failover Cluster(retries=”0”)策略防止出现数据重复添加等等其它问题!建议在设计接口时候把查询接口方法单独做一个接口提供查询。

0x03 dubbo的服务降级

  1. 服务降级的概念

    • 当某个非关键服务出现故障时,可以通过降级的方式来屏蔽这个服务,说白点就是给个默认返回。降级按层面可以分为人工降级和自动降级,按功能可以分为读服务降级和写服务降级。
    • 对一些非核心服务进行人工降级,在大促之前通过降级开关关闭哪些推荐内容、评价等对主流程没有影响的功能
    • 故障降级:比如调用的远程服务挂了,网络故障、或者 RPC 服务返回异常。 那么可以直接降级,降级的方案比如设置默认值、采用兜底数据(系统推荐的行为广告挂了,可以提前准备静态页面做返回)等等
    • 限流降级,在秒杀这种流量比较集中并且流量特别大的情况下,因为突发访问量特别大可能会导致系统支撑不了。这个时候可以采用限流来限制访问量。当达到阀值时,后续的请求被降级,比如进入排队页面,比如跳转到错误页(活动太火爆,稍后重试等)
  2. Dubbo提供的降级机制

    • 在Dubbo中提供了一个mock的配置,通过配置这个属性来实现当服务提供方出现网络异常或者挂掉以后,客户端不抛出异常,而是通过Mock数据返回自定义的数据。
  3. Dubbo服务降级的使用

    1. 定义一个类,实现需要mock的接口,并重写方法.假设需要mockIHelloService。那么类定义如下:
      1
      2
      3
      4
      5
      6
      public class HelloServiceMock implements IHelloService{
      @Override
      public String sayHello(){
      return "服务器忙,请稍后重试";
      }
      }
    2. 配置方式
      1. 通过xml配置文件配置:
        • 在服务提供方这边的<dubbo:service>标签中配置mock属性。如:
          • <dubbo:service interface="top.zyzling.IHelloService" mock="top.zyzling.HelloServiceMock">
      2. 通过注解方式配置:
        • 直接配置@Service注解的mock属性。如:
          • `@Service(mock=“top.zyzling.HelloServiceMock”)

评论