王有志,一个分享硬核Java技术的互金摸鱼侠

加入Java人的提桶跑路群共同富裕的Java人

上一篇中,我们已经在Spring Boot应用中集成了Dubbo,并注册了一个服务提供方和一个服务使用方。当然,生产环境中应用往往会部署多个节点,以此来保证服务的高可用,那么如何配置Dubbo的负载均衡策略呢?

下面我们以此为切入点,来介绍Dubbo在服务治理方面提供的高级特性的配置与使用。Dubbo默认支持6种配置来源:

  • JVM System Properties,JVM -D参数

  • System environment,JVM进程的环境变量

  • Externalized Configuration,外部化配置,从配置中心读取

  • Application Configuration,应用的属性配置,从Spring应用的Environment中提取"dubbo"打头的属性集

  • API//注解等编程接口采集的配置可以被理解成配置来源的一种,是直接面向用户编程的配置采集方式

  • 从classpath读取配置文件 dubbo.properties

在今天的内容中,我们只会涉及到Application Configuration,XML和注解这3种常见的配置方式。

Tips:本篇为基础内容,重点在配置和使用,不涉及任何实现原理和算法原理。

负载均衡

微服务中,负载均衡指的是将请求“合理”的分配在服务的不同节点间,以达到优化使用资源,提供高吞吐量,降低响应时间的目的。Dubbo 3.X中提供了7种负载均衡策略:

算法 特性 配置值 默认配置 说明
Weighted Random LoadBalance 加权随机 random 默认算法,默认权重相同
RoundRobin LoadBalance 加权轮询 roundrobin 借鉴于 Nginx 的平滑加权轮询算法,默认权重相同,
LeastActive LoadBalance 最少活跃优先 + 加权随机 leastactive 背后是能者多劳的思想
Shortest-Response LoadBalance 最短响应优先 + 加权随机 shortestresponse 更加关注响应速度
ConsistentHash LoadBalance 一致性哈希 consistenthash 确定的入参,确定的提供者,适用于有状态请求
P2C LoadBalance Power of Two Choice p2c 随机选择两个节点后,继续选择“连接数”较小的那个节点。
Adaptive LoadBalance 自适应负载均衡 adaptive 在 P2C 算法基础上,选择二者中 load 最小的那个节点

Dubbo支持为服务提供方和服务使用方配置负载均衡策略,当两者都配置了负载均衡策略,以服务使用方的负载均衡策略为准。

首先我们来看XML文件的配置方式,通过XML文件,可以为接口,方法配置负载均衡策略,先为服务提供方的DubboDemoService接口配置负载均衡策略:

<dubbo:service interface="com.wyz.api.DubboDemoService" ref="dubboDemoServiceImpl" loadbalance="roundrobin"/>

接着我们为服务使用方在调用DubboDemoService#say方法时配置负载均很策略:

<dubbo:reference id="DubboDemoService" interface="com.wyz.api.DubboDemoService">
<dubbo:method name="say" loadbalance="roundrobin"/>
</dubbo:reference>

接着我们使用Application文件配置负载均衡策略,通过Application文件,可以配置Dubbo应用的全局负载均衡策略,内容如下:

dubbo:
provider:
loadbalance: roundrobin
consumer:
loadbalance: roundrobin

最后注解的形式配置负载均衡策略,可以为接口和方法配置负载均衡策略配置,代码如下:

@DubboService(loadbalance = "roundrobin")
public class DubboDemoServiceImpl implements DubboDemoService { @Override
@DubboService(loadbalance = "leastactive")
public String say(String message) {
return "DubboProvider say : " + message;
}
}

集群容错

当配置好负载均衡策略后,程序一直稳定运行。可是突然有一天,集群中的某个节点不可用了,当请求“命中”了不可用的节点后,Dubbo会如何处理呢?

Dubbo提供了集群容错的能力,实现了9中针对集群中节点故障的处理方案:

策略 配置值 默认配置 特性 应用场景
Failover Cluster failover 失败自动切换,当出现失败,重试其它服务器 通常用于读操作,可以配置重试次数
Failfast Cluster failfast 快速失败,失败后立即报错 通常用于非幂等写操作
Failsafe Cluster failsafe 失败安全,出现异常时,直接忽略 通常用于写入审计日志
Failback Cluster failback 失败自动恢复,后台记录失败请求,定时重发 通常用于消息通知
Forking Cluster forking 并行调用多个服务器,只要一个成功即返回 通常用于实时性要求较高的读操作
Broadcast Cluster broadcast 广播调用所有提供者,逐个调用,任意一台报错则报错 缓存更新
Available Cluster available 调用目前可用的实例(只调用一个),如果当前没有可用的实例,则抛出异常 不需要负载均衡的场景
Mergeable Cluster mergeable 将集群中的调用结果聚合起来返回结果,通常和group一起配合使用 /
ZoneAware Cluster / 多注册中心订阅的场景,注册中心集群间的负载均衡 /

XML文件的形式依旧提供了接口及接口方法级别的集群容错策略配置

<dubbo:service interface="com.wyz.api.DubboDemoService" ref="dubboDemoServiceImpl" cluster="failover" retries="2"/>

其中retries是Failover Cluster策略的参数,设定了接口重试的次数(不含正常调用次数),例如,在上述配置中,正常调用失败后,至多会再调用两次。通过XML配置方法级别的集群容错策略与配置负载均衡策略一致,这里就不过多赘述了。

Application文件中可以配置全局的集群容错策略,内容如下:

dubbo:
provider:
cluster: failover
retries: 2

最后是注解配置方式,依旧是通过@DubboService来配置接口和接口方法级别的集群容错策略,代码如下:

@DubboService(cluster = "failover", retries = 2)
public class DubboDemoServiceImpl implements DubboDemoService { @Override
@DubboService(cluster = "failover", retries = 2)
public String say(String message) {
return "DubboProviderXML say : " + message;
}
}

服务降级

Dubbo自身提供的服务降级功能较为简陋,只提供了mock功能,如果想要体验功能完善的限流熔断等功能,可以使用Sentinel,Hystrix以及Resilience4j等Dubbo支持的专业的技术组件。由于Dubbo的服务降级功能较为简陋,这里只通过3种XML文件的配置方式了解服务降级的功能的配置即可。

配置方式一

<dubbo:service interface="com.wyz.api.DubboDemoService" ref="dubboDemoServiceImpl"  mock="true"/>

这种方式的配置中,需要在相同包下有类名 + Mock后缀的实现类,例如:DubboDemoServiceMock

public class DubboDemoServiceMock implements DubboDemoService {
@Override
public String say(String message) {
return "服务出错了!";
}
}

配置方式二

通过Mock类的全限名配置:

<dubbo:service interface="com.wyz.api.DubboDemoService" ref="dubboDemoServiceImpl"  mock="com.wyz.api.DubboDemoServiceMock"/>

配置方式三

使用Dubbo定义的表达式:mock="[fail|force]return|throw xxx"

  • [fail|force],默认值fail,表示调用失败后,或不进行方法调用直接强制执行mock方法;

  • return xxx,表示返回指定结果,需要符合接口的返回类型;

  • throw xxx,表示抛出指定异常。

我们举几个例子:

<dubbo:service interface="com.wyz.api.DubboDemoService" ref="dubboDemoServiceImpl"  mock="return fail"/>
<dubbo:service interface="com.wyz.api.DubboDemoService" ref="dubboDemoServiceImpl" mock="force:return false"/>
<dubbo:service interface="com.wyz.api.DubboDemoService" ref="dubboDemoServiceImpl" mock="fail:throw java.lang.NullPointException"/>

服务分组

允许通过分组的方式来区分同一个接口的不同实现方式。例如:为DubboXMLService接口添加两个不同的实现DubboXMLServiceImpl和NewDubboXMLServiceImpl。

public interface DubboXMLService {
String say(String message);
} public class DubboXMLServiceImpl implements DubboXMLService {
@Override
public String say(String message) {
return "DubboProviderXML say : " + message;
}
} public class NewDubboXMLServiceImpl implements DubboXMLService {
@Override
public String say(String message) {
return "NewDubboProviderXML say : " + message;
}
}

首先是通过XML文件配置服务提供方:

<bean id="dubboXMLServiceImpl" class="com.wyz.service.impl.DubboXMLServiceImpl"/>
<dubbo:service interface="com.wyz.api.DubboXMLService" ref="dubboXMLServiceImpl" group="XML-Provider"/> <bean id="newDubboXMLServiceImpl" class="com.wyz.service.impl.NewDubboXMLServiceImpl"/>
<dubbo:service interface="com.wyz.api.DubboXMLService" ref="newDubboXMLServiceImpl" group="New-XML-Provider"/>

接着来看服务使用方的配置:

<dubbo:reference id="dubboXMLService" interface="com.wyz.api.DubboXMLService" group="XML-Provider"/>
<dubbo:reference id="newDubboXMLService" interface="com.wyz.api.DubboXMLService" group="New-XML-Provider"/>

使用的话也非常简单,可以直接通过@Autowired方式注入不同分组的服务:

public class DubboConsumerXMLService implements CommandLineRunner {

  @Autowired
DubboXMLService dubboXMLService; @Autowired
DubboXMLService newDubboXMLService; @Override
public void run(String... args) {
String message = dubboXMLService.say("wyz");
System.out.println(message); String newMessage = newDubboXMLService.say("wyz");
System.out.println(newMessage);
}
}

再来看如何通过注解的方式进行配置:

@DubboService(group = "Annotation-Provider")
public class DubboAnnotationServiceImpl implements DubboAnnotationService {
@Override
public String say(String message) {
return "DubboProviderAnnotation say : " + message;
}
} @DubboService(group = "New-Annotation-Provider")
public class NewDubboAnnotationServiceImpl implements DubboAnnotationService {
@Override
public String say(String message) {
return "NewDubboProviderAnnotation say : " + message;
}
}

最后是通过注解使用不同分组的服务,注意这里要使用@DubboReference注入Bean:

@Component
public class DubboConsumerAnnotationService implements CommandLineRunner { @DubboReference(group = "Annotation-Provider")
DubboAnnotationService dubboAnnotationService; @DubboReference(group = "New-Annotation-Provider")
DubboAnnotationService newDubboAnnotationService; @Override
public void run(String... args) {
String message = dubboAnnotationService.say("wyz-Annotation");
System.out.println(message); String newMessage = newDubboAnnotationService.say("wyz-Annotation");
System.out.println(newMessage);
}
}

Tips:不推荐通过Application文件的方式进行配置。

服务版本

Dubbo中,接口并不能唯一的确定一个服务,只有明确接口+分组+版本号才能唯一的确定一个服务,例如:

<dubbo:service interface="com.wyz.api.DubboXMLService" ref="dubboXMLServiceImpl" group="XML-Provider" version="1.0.0"/>

服务区分版本常见于版本发布验证的场景中,集群中部分节点升级服务,并切换少许流量,验证成功后,再大范围升级节点,可以降低服务升级带来的风险

服务版本的配置与使用方式与服务分组一样,这里只展示XML文件的配置方式:

<bean id="dubboXMLServiceImpl" class="com.wyz.service.impl.DubboXMLServiceImpl"/>
<dubbo:service interface="com.wyz.api.DubboXMLService" ref="dubboXMLServiceImpl" version="1.0.0"/>

服务使用者的XML文件配置:

<dubbo:reference id="dubboXMLService" interface="com.wyz.api.DubboXMLService" version="1.0.0"/>

XML文件的配置方式可以直接使用@Autowired注入不同版本的服务,我们这里就不赘述了。


今天,我们一起了解并学习了如何配置和使用Dubbo提供的服务治理的能力。

除了上面提到的服务治理能力外,Dubbo还提供了服务路由的能力,Dubbo 2.7之前,可以通过<dubbo:route>标签来配置路由规则,但在Dubbo 2.7之后,官方移除了<dubbo:route>标签,引入了一套依赖于注册中心和配置中心的全新路由配置机制,后面会出一篇番外篇,将注册中心迁移到Nacos上,并学习如何配置路由规则。

如果本文对你有帮助的话,还请多多点赞支持。如果文章中出现任何错误,还请批评指正。最后欢迎大家关注分享硬核技术的金融摸鱼侠王有志,我们下次再见!

Dubbo的高级特性:服务治理篇的更多相关文章

  1. Dubbo之高级特性

    Dubbo 注意当启动服务时,该服务会占用本机一个端口号,故在一台电脑启动多个服务时需要在配置文件中更占用本机的端口号 <!--服务占用本机的端口-当本机启动多个服务时须保持不同--> & ...

  2. Dubbo高级特性实践-泛化调用

    引言 当后端Java服务用Dubbo协议作为RPC方案的基础,但部分消费方是前端Restful的PHP服务,不能直接调用,于是在中间架设了Router服务提供统一的基于HTTP的后端调用入口. 而Ro ...

  3. Dubbo 高级特性实践-泛化调用

    引言 当后端Java服务用Dubbo协议作为RPC方案的基础,但部分消费方是前端Restful的PHP服务,不能直接调用,于是在中间架设了Router服务提供统一的基于HTTP的后端调用入口. 而Ro ...

  4. 微服务浅谈&服务治理的演变过程

    这两天对互联网的架构演变进行了简单了解,并对微服务的出现很感兴趣,所以对相关知识进行了简单的整理与总结. 本篇文章先简单介绍了互联网架构的演变,进而介绍了服务化,最后介绍了微服务及最新的服务网格(Se ...

  5. 基于Nginx dyups模块的站点动态上下线并实现简单服务治理

    简介 今天主要讨论一下,对于分布式服务,站点如何平滑的上下线问题. 分布式服务 在分布式服务下,我们会用nginx做负载均衡, 业务站点访问某服务站点的时候, 统一走nginx, 然后nginx根据一 ...

  6. 分布式服务治理框架Dubbo的前世今生及应用实战

    Dubbo的出现背景 Dubbo从开源到现在,已经出现了接近10年时间,在国内各大企业被广泛应用. 它到底有什么魔力值得大家去追捧呢?本篇文章给大家做一个详细的说明. 大规模服务化对于服务治理的要求 ...

  7. 分布式服务治理框架dubbo

    Dubbo最主要功能有两个 1 RPC调用 2 SOA服务治理方案 Dubbo的架构 Dubbo常见的注册中心有2中,zookeeper以及redis 这篇文章讲解的是采用的zookeeper,要求读 ...

  8. Dubbo框架中的应用(两)--服务治理

    Dubbo服务治理了看法 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGlzaGVoZQ==/font/5a6L5L2T/fontsize/400/fi ...

  9. Dubbo框架应用之(二)--服务治理

    Dubbo服务治理全貌图 当我们现有ITOO平台系统的业务随着用户的逐渐增大,设计的业务越来越广,系统会异常的复杂,在大规模服务之前,我们可以采用的是RMI或Hessian等工具,暴露和引用远程服务, ...

  10. Dubbo 服务治理-mock实例

    转: Dubbo 服务治理-mock实例 老生住长亭 2017.02.28 10:56* 字数 514 阅读 2552评论 10喜欢 2 Dubbo的mock自己折腾的实例,配置信息有点简陋,有点粗鄙 ...

随机推荐

  1. ansible-kubeadm在线安装k8s v1.19-v1.20版本

    ansible-kubeadm在线安装k8s v1.19-v1.20版本 1. ansible-kubeadm在线安装k8s v1.19-v1.20版本 安装要求 确保所有节点系统时间一致 操作系统要 ...

  2. 开心档之MySQL 连接

    MySQL 连接 使用mysql二进制方式连接 您可以使用MySQL二进制方式进入到mysql命令提示符下来连接MySQL数据库. 实例 以下是从命令行中连接mysql服务器的简单实例: [root@ ...

  3. 深度学习--全连接层、高阶应用、GPU加速

    深度学习--全连接层.高阶应用.GPU加速 MSE均方差 Cross Entropy Loss:交叉熵损失 Entropy 熵: 1948年,香农将统计物理中熵的概念,引申到信道通信的过程中,从而开创 ...

  4. 密码学与网安——intro

    Terminology primitive: 原语 (一种不可分割的最基础操作,跟具体的视角和情形有关) 两个时间节点 1949年(1945年):Shannon 提出完全安全性,开始现代密码学 197 ...

  5. react项目使用less样式,配置less

    create-react-app脚手架创建的项目有sass配置项,使用的时候只需要装包即可,下面是less使用的方法 由于 create-react-app 脚手架中并没有配置关于 less 文件的解 ...

  6. 学node 之前你要知道这些

    初识nodejs   19年年底一个偶然的机会接到年会任务,有微信扫码登录.投票.弹幕等功能,于是决定用node 来写几个服务,结果也比较顺利.   当时用看了下koa2的官方文档,知道怎么连接数据库 ...

  7. AI 绘画基础 - 细数 Stable Diffusion 中的各种常用模型 【🧙 魔导士装备图鉴】

    AI 绘画新手魔导士在刚开始玩 Stable Diffusion 时总会遇到各种新的概念,让人困惑,其中就包括各种模型和他们之间的关系. 魔法师入门得先认识各种法师装备(各种模型),让我们遇到问题知道 ...

  8. python的docker环境配置

    docker环境配置 Docker基本操作指令, 下载安装参考 https://duoke360.com/tutorial/docker/install-docker docker + flask + ...

  9. 2020-10-16:CAS知道么?底层实现? 会引发什么问题?如何解决ABA问题?

    福哥答案2020-10-16:#福大大架构师每日一题# 简单回答:cmpxchg原子指令.aba,循环开销大,一个共享变量. [知乎](https://www.zhihu.com/question/4 ...

  10. 2022-07-09:总长度为n的数组中,所有长度为k的子序列里,有多少子序列的和为偶数?

    2022-07-09:总长度为n的数组中,所有长度为k的子序列里,有多少子序列的和为偶数? 答案2022-07-09: 方法一:递归,要i还是不要i. 方法二:动态规划.需要两张dp表. 代码用rus ...