在这一篇中,对一些个人开发时常用的配置参数进行记录。不保证准确,详情请见官方文档
1、启动时检查
简单的讲,就是如果A服务依赖了B服务,那么A在启动时会检查B服务能否提供服务,即A服务在启动时能否从注册中心拿到B服务的引用,如果拿不到,则会阻止A服务的启动,默认是开启的。在服务上线的时候,最好开启,能提早发现问题,比如A服务启动时需要通过B服务加载一些数据等,如果B服务没有启动,则A服务没办法加载到数据,即便启动后也是有问题的。
springboot
中关闭其配置一般使用配置文件的方式:
application.properties
dubbo.consumer.check=false
也可使用注解指定单个服务关闭检查 @DubboReference(check = false)
2、集群容错
在集群调用失败时,Dubbo 提供了多种容错方案,缺省为 failover
重试。
@DubboReference(cluster = "fialfast")
private OrderService orderService;
Failover Cluster
失败自动切换,当出现失败,重试其它服务器。通常用于读操作,但重试会带来更长延迟。可通过 retries="2"
来设置重试次数(不含第一次)。
注:为了保证接口幂等性,在写操作上不要使用重试,避免因网络波动重试导致的订单多次支付或多次插入数据库等情况。
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"})
3、负载均衡策略
Random LoadBalance:随机,按权重设置随机概率。缺省配置为随机。
RoundRobin LoadBalance:轮询,按公约后的权重设置轮询比率。
LeastActive LoadBalance:最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差。
ConsistentHash LoadBalance:一致性 Hash,相同参数的请求总是发到同一提供者。
springboot
中常用的配置方式如下:
- 配置于提供者
@Service
@DubboService(loadbalance = "leastactive")
public class OrderServiceImpl implements OrderService {/*...*/}
- 配置于消费者
@DubboReference(loadbalance = "leastactive", methods = {@Method(name = "getOrder", loadbalance = "roundrobin")})
private OrderService orderService;
一般都是配置在服务级别,很少会配置到方法级别。
4、只订阅不注册
即共用一个注册中心时,避免正在开发的提供者P1和消费者C1对当前注册中心所在环境下的稳定的P和C造成影响,即可配置提供者P1只订阅注册中心的其他服务,但是不将自己注册上去,避免其他消费者调用到P1导致出现问题。当然也可以指定一个独一无二的分组或版本号,这样也可以,但最好还是不要注册上去,避免有些消费者指定的分组和版本号为*
。
dubbo.registry.register=false
// 直连,如果版本号或分组不同,则也要指定,格式为:url="dubbo//ip:port" 端口是rpc端口,不是应用端口
@DubboReference(check = false, group = "test1", version = "1.0.0", url = "dubbo://192.168.0.100:20885")
5、多协议
Dubbo 允许配置多协议,在不同服务上支持不同协议或者同一服务上同时支持多种协议。
比如,文件上传等传输数据较大的接口,就不适合使用dubbo
协议,可以更换为http
协议,参考:
6、多分组/多版本
对于一个接口有多种实现的时候,可以使用不同的分组进行区分,在服务调用的时候指定分组即可,也可指定任意分组。
// 提供者针对特定个性化客户指定特定分组,比如适用于客户2的个性化接口分组
@DubboService(group = "customer2", version = "1.0.0")
// 消费者,可指定多个分组,使用逗号分隔
@DubboReference(group = "customer1,customer2", version = "1.0.0")
// 或通用接口,任意分组
@DubboReference(group = "*", version = "1.0.0")
在这测试过程中,为了省事,
TestServiceImpl
同时实现了TestService1
和TestService2
接口,但是发现注册到注册中心的只有TestService1
,将实现类拆开为两个分别实现后才在注册中心看到TestService2
。当然,这个只是测试省事时发现的,一般开发过程中,也不会一个类同时实现两个不同的业务接口的。
多版本与多分组一致,可以指定特定的版本号,也可使用星号*
指定任意版本。
7、参数验证
基于JSR303
标准的验证需要添加如下maven
依赖:
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.0.0.GA</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.2.0.Final</version>
</dependency>
具体的校验注解或自定义校验方式这里就不再过多叙述。
// 消费者端进行校验
@DubboReference(validation = true)
// 提供者端进行校验
@DubboService(validation = true)
8、泛化调用
官方文档
<dubbo:reference id="barService" interface="com.foo.BarService" generic="true" />
GenericService barService = (GenericService) applicationContext.getBean("barService");
Object result = barService.$invoke("sayHello", new String[] { "java.lang.String" }, new Object[] { "World" });
通过API方式使用泛化可参考这篇博客。