扯淡:
Dubbo默认的远程调用超时时间为 1 秒,超时重试次数为2次(加上原本的一次总共3次),而在实际项目中不允许超时的场景很多, 例如,添加数据的业务中重试会避免重复数据、发送短信的业务可能重复发送等。在【上一章】的基础上参看官网引入dubbo的几种配置方式、引入超时重试的配置。推荐xml配置方式。
个人学习总结:
链接:【springboot、springcloud、docker 等,学习目录】
官网地址(重要):
http://dubbo.apache.org/en-us/docs/user/quick-start.html
一、Dubbo的配置方式:
总结三种:
1、注解配置: 上一章,使用@Service、@Reference,有些版本的dubbo还需要开启dubbo的注解,此种最简单,但是没有提供控制到方法级别的注解。此种方式使用retries属性指定超时重试有很多坑,容易出错。
2、Dubbo xml 配置: 此种方式很直观,可直接参考官网schema配置参考手册,本章使用超时重试机制也是在此种方式上验证。推荐使用。
3、使用API的方式: 将每一个组件手动创建到容器中,使用@Service、@Reference。
二、项目构建
此处只有部分代码,完整代码请【下载源码】。
1、pom依赖:
上一章使用的 springboot 的 starter,点进去可以看到它包含了 dubbo、zk 的相关依赖,我们这章不使用封装好的starter,直接引入dubbo 和 zk 的相关依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.7</version>
<exclusions>
<exclusion>
<artifactId>spring</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.6</version>
<exclusions>
<exclusion>
<artifactId>slf4j-log4j12</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>0.1</version>
</dependency>
三、Dubbo xml 方式配置:
新建springboot-dubbo-service-xml 模块
1、在resources 下新建provider.xml (服务提供者)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!-- 当前服务的名字(同样的服务名字相同,不要和别的服务同名) -->
<!--<dubbo:application name="user-service-provider-xml"></dubbo:application>-->
<!-- 注册中心的位置 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181"></dubbo:registry>
<!--<dubbo:registry protocol="zookeeper" address="127.0.0.1:2181"></dubbo:registry>-->
<!-- 3通信规则 -->
<dubbo:protocol name="dubbo" port="20882"></dubbo:protocol>
<!--统一设置服务提供方的规则 -->
<dubbo:provider timeout="3000"></dubbo:provider>
<!-- 用户服务 ref:指向服务实现对象 spring 容器中的名字 -->
<!-- 控制到类 -->
<dubbo:service interface="com.coolron.service.user.UserService" ref="userService" timeout="1000" version="1.0.0" >
<!-- 方法级别的控制 retries 默认是2 指定为0 表示禁止 超时重试 -->
<dubbo:method name="getAllUser" timeout="1000" retries="0"></dubbo:method>
</dubbo:service>
<!-- 权限服务 -->
<dubbo:service interface="com.coolron.service.permission.PermissionService" ref="permissionService" version="1.0.0" >
</dubbo:service>
<!-- 角色服务 -->
<dubbo:service interface="com.coolron.service.permission.RoleService" ref="roleService" version="1.0.0" >
</dubbo:service>
<!-- 服务的实现类 也可在 实现类上加上 @Service(Spring 的注解 不要与 dubbo的 service 注解混淆 ) -->
<!--<bean id="userService" class="com.coolron.service.impl.user.UserServiceImpl"></bean>-->
<!-- 连接监控中心 -->
<!--<dubbo:monitor protocol="registry"></dubbo:monitor>-->
<!--<dubbo:monitor address="127.0.0.1:7001"></dubbo:monitor>-->
</beans>
相关标签的使用请参看官网,写的非常详细。
2、属性配置:
第一步provider 的配置已经可以完成dubbo服务的暴露了,但是如果有很多配置,又不想写冗余代码,可以使用属性配置作为缺省值。
2.1、在resources下新建dubbo.properties配置文件:
1### 此处的配置只作为缺省 #####
2### JVM 启动 -D 参数优先 > XML > Properties #####
3# 应用名
4dubbo.application.name=properties-provider
5# 注册中心地址
6dubbo.registry.address=zookeeper://127.0.0.0:2181
7# 调用协议地址
8dubbo.protocol.name=dubbo
9dubbo.protocol.port=38080
2.2、问题:若xml中和properties中有相同配置,怎么选择?
看官网
优先级:JVM -D参数 > XML > properties
3、@ImportResource导入服务配置
/**
* @Auther: xf
* @Date: 2018/12/01 22:55
* @Description:
*/
@ImportResource(locations = {"classpath:provider.xml"})
@SpringBootApplication
@MapperScan("com.coolron.dao.*")
public class XmlServiceApplication {
public static void main(String[] args) {
SpringApplication.run(XmlServiceApplication.class, args);
}
}
4、启动:dubbo admin 监控、springboot-dubbo-service-xml服务
超时重试机制:
1、超时: 在约定的时间内服务提供方没有返回结果,则认为调用失败。
2、重试: 超时后,会再次调用,如果重试次数达到约定次数则抛出异常。默认2次。
3、示例:(类、方法上都可以指定)
1<!-- 方法级别的控制 超时时间一秒 禁止重试 -->
2<dubbo:method name="getAllUser" timeout="1000" retries="0"></dubbo:method>
4、测试:
4.1、服务消费者使用上一章的服务,启动
4.2、注释超时重试配置
<dubbo:service interface="com.coolron.service.user.UserService" ref="userService" timeout="1000" version="1.0.0" >
<!-- 方法级别的控制 retries 默认是2 指定为0 表示禁止 超时重试 -->
<!--<dubbo:method name="getAllUser" timeout="1000" retries="0"></dubbo:method>-->
</dubbo:service>
4.3、请求接口:http://localhost:8070/user/getUserList 请求正常。
将服务提供方的方法打上断点后控制台日志:超时时间1秒,重试3次。
4.4、将超时重试的注释去掉,加上断点结果如下:
5、建议:
- 业务复杂可适当设置大一点的超时时间,超时并不代表异常,所以超时重试可能带来重复执行代码,容易出现多余的数据。需根据业务设置。
- 超时重试建议设置到服务提供方,因为服务消费方只需要交互数据,服务提供方注重的是业务逻辑,所以,业务的复杂度,允不允许超时重试业务提供方最清楚。
四、注解API 方式配置:
1、新建springboot-dubbo-service-api模块
2、新建配置类:
/**
* @Auther: xf
* @Date: 2018/12/01 23:58
* @Description: dubbo api 配置类
*/
@Configuration
public class ServiceDubboConfig {
@Bean
public ApplicationConfig applicationConfig() {
ApplicationConfig applicationConfig = new ApplicationConfig();
applicationConfig.setName("service-provider-api");
return applicationConfig;
}
@Bean
public RegistryConfig registryConfig() {
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.setProtocol("zookeeper");
registryConfig.setAddress("127.0.0.1:2181");
return registryConfig;
}
//<dubbo:protocol name="dubbo" port="20882"></dubbo:protocol>
@Bean
public ProtocolConfig protocolConfig() {
ProtocolConfig protocolConfig = new ProtocolConfig();
protocolConfig.setName("dubbo");
protocolConfig.setPort(20880);
return protocolConfig;
}
/**
*<dubbo:service interface="com.atguigu.gmall.service.UserService"
ref="userService" timeout="1000" version="1.0.0">
<dubbo:method name="getUserAddressList" timeout="1000"></dubbo:method>
</dubbo:service>
*/
@Bean
public ServiceConfig<UserService> serviceConfig(){
ServiceConfig<UserService> serviceConfig = new ServiceConfig<UserService>();
serviceConfig.setApplication(applicationConfig());
serviceConfig.setRegistry(registryConfig()); // 多个注册中心可以用setRegistries()
serviceConfig.setProtocol(protocolConfig()); // 多个协议可以用setProtocols()
serviceConfig.setInterface(UserService.class);
serviceConfig.setRef(new UserServiceImpl());
serviceConfig.setVersion("1.0.0");
return serviceConfig;
}
// <dubbo:provider timeout="1000"></dubbo:provider>
@Bean
public ProviderConfig providerConfig() {
ProviderConfig providerConfig = new ProviderConfig();
providerConfig.setTimeout(5000);
return providerConfig;
}
// <dubbo:monitor address="127.0.0.1:7070"></dubbo:monitor>
// @Bean
// public MonitorConfig monitorConfig() {
// MonitorConfig monitorConfig = new MonitorConfig();
// monitorConfig.setAddress("127.0.0.1:7070");
// monitorConfig.setProtocol("registry");
// return monitorConfig;
// }
}
3、配置扫描
@DubboComponentScan(basePackages = "com.coolron.service.impl")
@SpringBootApplication
@MapperScan("com.coolron.dao.*")
public class ApiServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ApiServiceApplication.class, args);
}
}
注解api 配置完成,详细请参看官网。
总结:
- dubbo提供了三种配置方式,dubbo xml为重点配置方式,也是官网资料相对其他几种较多的,可结合属性配置减少冗余代码。
- 超时并不代表代码有异常,默认超时会重连2次,避免重复数据等问题,业务中慎重考虑使用。且超时重连机制建议在服务提供方配置,其他地方不配置。
- 本章中xml的配置只在服务提供方有设计,服务消费方类似,使用dubbo:reference 标签接口,请参看官网。
代码地址:
https://gitee.com/cpla026/dubbo/tree/master/springboot-dubbo-parent
个人微信公众号,谢谢支持!