当前位置:   article > 正文

dubbo(8):高可用_@dubboreference url

@dubboreference url

一、Zookeeper宕机与dubbo直连

    zookeeper注册中心宕机还可以消费dubbo暴露的服务。

    原因:健壮性

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

    高可用,通过设计减少系统不能提供服务的时间。也可以使用直连的方式绕过注册中心,直接连接服务提供者,使用url指向服务提供者地址。

  1. @DubboReference(url="192.168.1.2:20080") // 去dubbo注册中心中寻找
  2. private UserService userService;

二、负载均衡机制

    在集群负载均衡时,dubbo提供了多种均衡策略,缺省为Random随机调用。负载均衡策略:

  • Random LoadBalance:随机,按权重设置随机概率。在一个截面上碰撞的概率高,但调用量越大分布越均匀,而且按概率使用权重后也比较均匀,有利于动态调整提供者权重。
  • RoundRobin LoadBalance:轮询,按公约后的权重设置轮询比率。可能会存在慢的提供者累积请求的问题,比如,第二台机器很慢,但没挂。当请求调用到第二台机器时就卡在那,久而久之,所有请求都卡在调用第二台机器上。
  • Leastactive LoadBalance:自动感知策略。如果某个机器性能越差,那么接收的请求越少,越不活跃,此时就会给不活跃的性能差的机器分配更少的请求。
  • ConsistantHash LoadBalance,一致性 Hash 算法。即相同参数的请求一定分发到一个provider。当provider挂掉的时候,会基于虚拟节点均匀分配剩余的流量,抖动不会太大。

    复制两份服务提供者,测试负载均衡。

    启动3服务提供者和消费者。

多次访问http://localhost:8802/Order/initOrder/1查看

改变负载均衡机制

    官方文档中提供了4种配置方法,注解版则在相应的注解中配置,例如:@DubboReference(loadbalance = "roundrobin")

服务端服务级别

<dubbo:service interface="..." loadbalance="roundrobin" />

客户端服务级别

<dubbo:reference interface="..." loadbalance="roundrobin" />

服务端方法级别

  1. <dubbo:service interface="...">
  2. <dubbo:method name="..." loadbalance="roundrobin"/>
  3. </dubbo:service>

客户端方法级别

  1. <dubbo:reference interface="...">
  2. <dubbo:method name="..." loadbalance="roundrobin"/>
  3. </dubbo:reference>

    服务器负载均衡策略一般根据不同情况做相应的调整,所以一般会在可视化界面进行调整。

三、服务降级

    降级 Dubbo 服务。可以通过服务降级功能临时屏蔽某个出错的非关键服务,并定义降级后的返回策略。向注册中心写入动态配置覆盖规则:

  1. RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
  2. Registry registry = registryFactory.getRegistry(URL.valueOf("zookeeper://10.20.153.10:2181"));
  3. registry.register(URL.valueOf("override://0.0.0.0/com.foo.BarService?category=configurators&dynamic=false&application=foo&mock=force:return+null"));

其中:

  • mock=force:return+null 表示消费方对该服务的方法调用都直接返回 null 值,不发起远程调用。用来屏蔽不重要服务不可用时对调用方的影响。
  • 还可以改为 mock=fail:return+null 表示消费方对该服务的方法调用在失败后,再返回 null 值,不抛异常。用来容忍不重要服务不稳定时对调用方的影响。

四、集群容错

集群调用失败时,Dubbo 提供的容错方案

在集群调用失败时,Dubbo 提供了多种容错方案,缺省为 failover 重试。

 

各节点关系:

  • 这里的 Invoker 是 Provider 的一个可调用 Service 的抽象,Invoker 封装了 Provider 地址及 Service 接口信息
  • Directory 代表多个 Invoker,可以把它看成 List<Invoker> ,但与 List 不同的是,它的值可能是动态变化的,比如注册中心推送变更
  • Cluster 将 Directory 中的多个 Invoker 伪装成一个 Invoker,对上层透明,伪装过程包含了容错逻辑,调用失败后,重试另一个
  • Router 负责从多个 Invoker 中按路由规则选出子集,比如读写分离,应用隔离等
  • LoadBalance 负责从多个 Invoker 中选出具体的一个用于本次调用,选的过程包含了负载均衡算法,调用失败后,需要重选

集群容错模式

可以自行扩展集群容错策略,参见:集群扩展

Failover Cluster

失败自动切换,当出现失败,重试其它服务器。通常用于读操作,但重试会带来更长延迟。可通过 retries="2" 来设置重试次数(不含第一次)。

重试次数配置如下:

<dubbo:service retries="2" />

<dubbo:reference retries="2" />

  1. <dubbo:reference>
  2. <dubbo:method name="findFoo" retries="2" />
  3. </dubbo:reference>

提示

该配置为缺省配置

Failfast Cluster

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

Failsafe Cluster

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

Failback Cluster

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

Forking Cluster

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

Broadcast Cluster

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

现在广播调用中,可以通过 broadcast.fail.percent 配置节点调用失败的比例,当达到这个比例后,BroadcastClusterInvoker 将不再调用其他节点,直接抛出异常。 broadcast.fail.percent 取值在 0~100 范围内。默认情况下当全部调用失败后,才会抛出异常。 broadcast.fail.percent 只是控制的当失败后是否继续调用其他节点,并不改变结果(任意一台报错则报错)。broadcast.fail.percent 参数 在 dubbo2.7.10 及以上版本生效。

Broadcast Cluster 配置 broadcast.fail.percent。

broadcast.fail.percent=20 代表了当 20% 的节点调用失败就抛出异常,不再调用其他节点。

@reference(cluster = "broadcast", parameters = {"broadcast.fail.percent", "20"})

提示

2.1.0 开始支持

集群模式配置

按照以下示例在服务提供方和消费方配置集群模式

<dubbo:service cluster="failsafe" />

<dubbo:reference cluster="failsafe" />

五、路由规则

通过 Dubbo 中的路由规则做服务治理

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

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

后续我们计划在 2.6.x 版本的基础上继续增强脚本路由功能。

条件路由

您可以随时在服务治理控制台 Dubbo-Admin 写入路由规则

简介

  • 应用粒度

    1. # app1的消费者只能消费所有端口为20880的服务实例
    2. # app2的消费者只能消费所有端口为20881的服务实例
    3. ---
    4. scope: application
    5. force: true
    6. runtime: true
    7. enabled: true
    8. key: governance-conditionrouter-consumer
    9. conditions:
    10. - application=app1 => address=*:20880
    11. - application=app2 => address=*:20881
    12. ...
  • 服务粒度

    1. # DemoService的sayHello方法只能消费所有端口为20880的服务实例
    2. # DemoService的sayHi方法只能消费所有端口为20881的服务实例
    3. ---
    4. scope: service
    5. force: true
    6. runtime: true
    7. enabled: true
    8. key: org.apache.dubbo.samples.governance.api.DemoService
    9. conditions:
    10. - method=sayHello => address=*:20880
    11. - method=sayHi => address=*:20881
    12. ...

规则详解

各字段含义

  • scope表示路由规则的作用粒度,scope的取值会决定key的取值。必填
    • service 服务粒度
    • application 应用粒度
  • Key明确规则体作用在哪个服务或应用。必填
    • scope=service时,key取值为[{group}:]{service}[:{version}]的组合
    • scope=application时,key取值为application名称
  • enabled=true 当前路由规则是否生效,可不填,缺省生效。
  • force=false 当路由结果为空时,是否强制执行,如果不强制执行,路由结果为空的路由规则将自动失效,可不填,缺省为 false
  • runtime=false 是否在每次调用时执行路由规则,否则只在提供者地址列表变更时预先执行并缓存结果,调用时直接从缓存中获取路由结果。如果用了参数路由,必须设为 true,需要注意设置会影响调用的性能,可不填,缺省为 false
  • priority=1 路由规则的优先级,用于排序,优先级越大越靠前执行,可不填,缺省为 0
  • conditions 定义具体的路由规则内容。必填

Conditions规则体

`conditions`部分是规则的主体,由1到任意多条规则组成,下面我们就每个规则的配置语法做详细说明:
  1. 格式
  • => 之前的为消费者匹配条件,所有参数和消费者的 URL 进行对比,当消费者满足匹配条件时,对该消费者执行后面的过滤规则。
  • => 之后为提供者地址列表的过滤条件,所有参数和提供者的 URL 进行对比,消费者最终只拿到过滤后的地址列表。
  • 如果匹配条件为空,表示对所有消费方应用,如:=> host != 10.20.153.11
  • 如果过滤条件为空,表示禁止访问,如:host = 10.20.153.10 =>
  1. 表达式

参数支持:

  • 服务调用信息,如:method, argument 等,暂不支持参数路由
  • URL 本身的字段,如:protocol, host, port 等
  • 以及 URL 上的所有参数,如:application, organization 等

条件支持:

  • 等号 = 表示"匹配",如:host = 10.20.153.10
  • 不等号 != 表示"不匹配",如:host != 10.20.153.10

值支持:

  • 以逗号 , 分隔多个值,如:host != 10.20.153.10,10.20.153.11
  • 以星号 * 结尾,表示通配,如:host != 10.20.*
  • 以美元符 $ 开头,表示引用消费者参数,如:host = $host
  1. Condition示例
  • 排除预发布机:
=> host != 172.22.3.91
  • 白名单:
register.ip != 10.20.153.10,10.20.153.11 =>

注意

一个服务只能有一条白名单规则,否则两条规则交叉,就都被筛选掉了

  • 黑名单:
register.ip = 10.20.153.10,10.20.153.11 =>
  • 服务寄宿在应用上,只暴露一部分的机器,防止整个集群挂掉:
=> host = 172.22.3.1*,172.22.3.2*
  • 为重要应用提供额外的机器:
application != kylin => host != 172.22.3.95,172.22.3.96
  • 读写分离:
  1. method = find*,list*,get*,is* => host = 172.22.3.94,172.22.3.95,172.22.3.96
  2. method != find*,list*,get*,is* => host = 172.22.3.97,172.22.3.98
  • 前后台分离:
  1. application = bops => host = 172.22.3.91,172.22.3.92,172.22.3.93
  2. application != bops => host = 172.22.3.94,172.22.3.95,172.22.3.96
  • 隔离不同机房网段:
host != 172.22.3.* => host != 172.22.3.*
  • 提供者与消费者部署在同集群内,本机只访问本机的服务:
=> host = $host

标签路由规则

简介

标签路由通过将某一个或多个服务的提供者划分到同一个分组,约束流量只在指定分组中流转,从而实现流量隔离的目的,可以作为蓝绿发布、灰度发布等场景的能力基础。

Provider

标签主要是指对Provider端应用实例的分组,目前有两种方式可以完成实例分组,分别是动态规则打标静态规则打标,其中动态规则相较于静态规则优先级更高,而当两种规则同时存在且出现冲突时,将以动态规则为准。

  • 动态规则打标,可随时在服务治理控制台下发标签归组规则

    1. # governance-tagrouter-provider应用增加了两个标签分组tag1和tag2
    2. # tag1包含一个实例 127.0.0.1:20880
    3. # tag2包含一个实例 127.0.0.1:20881
    4. ---
    5. force: false
    6. runtime: true
    7. enabled: true
    8. key: governance-tagrouter-provider
    9. tags:
    10. - name: tag1
    11. addresses: ["127.0.0.1:20880"]
    12. - name: tag2
    13. addresses: ["127.0.0.1:20881"]
    14. ...
  • 静态打标

    <dubbo:provider tag="tag1"/>
    

    or

    <dubbo:service tag="tag1"/>
    

    or

    java -jar xxx-provider.jar -Ddubbo.provider.tag={the tag you want, may come from OS ENV}
    

Consumer

RpcContext.getContext().setAttachment(Constants.REQUEST_TAG_KEY,"tag1");

请求标签的作用域为每一次 invocation,使用 attachment 来传递请求标签,注意保存在 attachment 中的值将会在一次完整的远程调用中持续传递,得益于这样的特性,我们只需要在起始调用时,通过一行代码的设置,达到标签的持续传递。

目前仅仅支持 hardcoding 的方式设置 requestTag。注意到 RpcContext 是线程绑定的,优雅的使用 TagRouter 特性,建议通过 servlet 过滤器(在 web 环境下),或者定制的 SPI 过滤器设置 requestTag。

规则详解

格式

  • Key明确规则体作用到哪个应用。必填
  • enabled=true 当前路由规则是否生效,可不填,缺省生效。
  • force=false 当路由结果为空时,是否强制执行,如果不强制执行,路由结果为空的路由规则将自动失效,可不填,缺省为 false
  • runtime=false 是否在每次调用时执行路由规则,否则只在提供者地址列表变更时预先执行并缓存结果,调用时直接从缓存中获取路由结果。如果用了参数路由,必须设为 true,需要注意设置会影响调用的性能,可不填,缺省为 false
  • priority=1 路由规则的优先级,用于排序,优先级越大越靠前执行,可不填,缺省为 0
  • tags 定义具体的标签分组内容,可定义任意n(n>=1)个标签并为每个标签指定实例列表。必填
    • name, 标签名称
  • addresses, 当前标签包含的实例列表

降级约定

  1. request.tag=tag1 时优先选择 标记了tag=tag1 的 provider。若集群中不存在与请求标记对应的服务,默认将降级请求 tag为空的provider;如果要改变这种默认行为,即找不到匹配tag1的provider返回异常,需设置request.tag.force=true

  2. request.tag未设置时,只会匹配tag为空的provider。即使集群中存在可用的服务,若 tag 不匹配也就无法调用,这与约定1不同,携带标签的请求可以降级访问到无标签的服务,但不携带标签/携带其他种类标签的请求永远无法访问到其他标签的服务。

提示

2.6.x 版本以及更早的版本请使用老版本路由规则

自定义路由参考路由扩展

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/165721
推荐阅读
相关标签
  

闽ICP备14008679号