七、Dubbo配置
所有的配置在官方文档都有介绍
dubbo配置官网参考 :Schema 配置参考手册 | Apache Dubbo 、用法示例 | Apache Dubbo
在于SpringBoot整合的配置文件 application.properties 中的配置,和这些标签是一一对应的,所有标签均可在配置文件中进行配置。
1、配置原则
Duboo 对这些配置,让其生效,有三种策略:
-
JVM 启动 -D 参数优先,这样可以使用户在部署和启动时进行参数重写,比如在启动时需改变协议的端口。
-
XML 次之,如果在 XML 中有配置,则 dubbo.properties 中的相应配置项无效。
-
Properties 最后,相当于缺省值,只有 XML 没有配置时,dubbo.properties 的相应配置项才会生效,通常用于共享公共配置,比如应用名。
2、启动时检查
在启动时检查依赖的服务是否可用
Dubbo 缺省会在启动时检查依赖的服务是否可用,不可用时会抛出异常,阻止 Spring 初始化完成,以便上线时,能及早发现问题,默认 check="true"
。
可以通过 check="false"
关闭检查,比如,测试时,有些服务不关心,或者出现了循环依赖,必须有一方先启动。
另外,如果你的 Spring 容器是懒加载的,或者通过 API 编程延迟引用服务,请关闭 check,否则服务临时不可用时,会抛出异常,拿到 null 引用,如果 check="false"
,总是会返回引用,当服务恢复时,能自动连上。
操作示例:
在consumer.xml中修改配置:
关闭某个服务的启动时检查 (没有提供者时报错):
<!-- 3、生成远程服务代理,可以和本地bean一样使用demoService -->
<!--声明需要调用的远程服务的接口;生成远程服务代理 -->
<dubbo:reference interface="com.wlw.dubbo.service.UserService"
id="userService" check="false">
</dubbo:reference>
关闭所有服务的启动时检查 (没有提供者时报错):
<!-- 配置所有消费者的统一规则: 所有的服务启动都不检查-->
<dubbo:consumer check="false"></dubbo:consumer>
关闭注册中心启动时检查 (注册订阅失败时报错):
<dubbo:registry check="false" />
3、超时时间 与重试次数
超时时间的配置:由于网络或服务端不可靠,会导致调用出现一种不确定的中间状态(超时)。为了避免超时导致客户端资源(线程)挂起耗尽,必须设置超时时间。
重试次数的配置:失败自动切换,当出现失败,重试其它服务器(如果有的话),但重试会带来更长延迟。可通过 retries=“2” 来设置重试次数(不含第一次)。
<!-- 3、生成远程服务代理,可以和本地bean一样使用demoService -->
<!--声明需要调用的远程服务的接口;生成远程服务代理 -->
<!-- 配置生效优先级:
1)、精确优先 (方法级优先,接口级次之,全局配置再次之)
2)、消费者设置优先(如果级别一样,则消费方优先,提供方次之)
-->
<!--超时时间: timeout="0" 默认是1000ms-->
<!--重试次数 retries="" 不包含第一次调用,0代表不重试;
幂等的方法(设置重试次数)比如:查询、删除、修改操作
非幂等的方法(不能设置重试次数)比如:新增
-->
<dubbo:reference interface="com.wlw.dubbo.service.UserService"
id="userService" timeout="5000" retries="2">
<!--精确到方法的配置-->
<dubbo:method name="getUserAddressList" timeout="1000"></dubbo:method>
</dubbo:reference>
4、XML 配置覆盖关系
以 timeout 为例,下图显示了配置的查找顺序,其它 retries, loadbalance, actives 等类似:
- 方法级优先,接口级次之,全局配置再次之。
- 如果级别一样,则消费方优先,提供方次之。
其中,服务提供方配置,通过 URL 经由注册中心传递给消费方。
dubbo推荐在Provider上尽量多配置Consumer端属性:
-
1、作服务的提供者,比服务使用方更清楚服务性能参数,如调用的超时时间,合理的重试次数,等等
-
2、在Provider配置后,Consumer不配置则会使用Provider的配置值,即Provider配置可以作为Consumer的缺省值。否则,Consumer会使用Consumer端的全局设置,这对于Provider不可控的,并且往往是不合理的
5、多版本
在 Dubbo 中为同一个服务配置多个版本
当一个接口实现,出现不兼容升级时,可以用版本号过渡,版本号不同的服务相互间不引用。
可以按照以下的步骤进行版本迁移:
- 在低压力时间段,先升级一半提供者为新版本
- 再将所有消费者升级为新版本
- 然后将剩下的一半提供者升级为新版本
provider.xml:
<!-- 4、暴露服务 ref:指向服务的真正的实现对象 -->
<!-- 老服务 -->
<dubbo:service interface="com.wlw.dubbo.service.UserService"
ref="userServiceImpl01" timeout="2000" version="1.0.0">
</dubbo:service>
<!-- 服务的实现 -->
<bean id="userServiceImpl01" class="com.wlw.dubbo.service.impl.UserServiceImpl"></bean>
<!-- 新服务 -->
<dubbo:service interface="com.wlw.dubbo.service.UserService"
ref="userServiceImpl02" timeout="2000" version="2.0.0">
</dubbo:service>
<bean id="userServiceImpl02" class="com.wlw.dubbo.service.impl.UserServiceImpl2"></bean>
consumer.xml:指定哪个版本的服务,这样在启动时,就会调用对应的方法
<dubbo:reference interface="com.wlw.dubbo.service.UserService"
id="userService" timeout="5000" retries="2" version="2.0.0">
<!--精确到方法的配置-->
<dubbo:method name="getUserAddressList" timeout="1000"></dubbo:method>
</dubbo:reference>
-
如果不需要区分版本,可以按照以下的方式配置 :version="*",它会随机选择版本服务。提示:
2.2.0
以上版本支持<dubbo:reference interface="com.wlw.dubbo.service.UserService" id="userService" timeout="5000" retries="2" version="*"> <!--精确到方法的配置--> <dubbo:method name="getUserAddressList" timeout="1000"></dubbo:method> </dubbo:reference>
6、本地存根
远程服务后,客户端通常只剩下接口,而实现全在服务器端,但提供方有些时候想在客户端也执行部分逻辑,比如:做 ThreadLocal 缓存,提前验证参数,调用失败后伪造容错数据等等,此时就需要在 API 中带上 Stub,客户端生成 Proxy 实例,会把 Proxy 通过构造函数传给 Stub 1,然后把 Stub 暴露给用户,Stub 可以决定要不要去调 Proxy。
我们这是在消费者中配置:(在生产中应该在公共接口层对接口进行配置)
增加UserServiceStub:
package com.wlw.dubbo.service.impl;
import com.wlw.dubbo.bean.UserAddress;
import com.wlw.dubbo.service.UserService;
import org.springframework.util.StringUtils;
import java.util.List;
/**
* 本地存根
*/
public class UserServiceStub implements UserService {
private final UserService userService;
/**
* 构造函数传入真正的远程代理对象
* 传入的是userService 的远程代理对象
* @param userService
*/
public UserServiceStub(UserService userService) {
this.userService = userService;
}
@Override
public List<UserAddress> getUserAddressList(String userId) {
System.out.println("UserServiceStub..............");
if(!StringUtils.isEmpty(userId)) {
return userService.getUserAddressList(userId);
}
return null;
}
}
consumer.xml:增加配置:
<dubbo:reference interface="com.wlw.dubbo.service.UserService"
id="userService" timeout="5000" retries="2" version="2.0.0"
stub="com.wlw.dubbo.service.impl.UserServiceStub">
<!--精确到方法的配置-->
<dubbo:method name="getUserAddressList" timeout="1000"></dubbo:method>
</dubbo:reference>
测试结果:
7、配置 与SpringBoot整合的三种方式
第一种(也就是六、Dubbo与SpringBoot整合)使用的方式:
- 导入依赖
- 配置文件 application.properties 中增加配置
- 提供者:暴漏服务,通过注解(com.alibaba.dubbo.config.annotation.Service) 来实现;消费者:远程引用指定的服务,注解:com.alibaba.dubbo.config.annotation.Reference;
- 启动类开启Dubbo,注解:@EnableDubbo
第二种(保留Dubbo 相关的xml配置文件,这样就可以做到方法级别的配置,上面第一种是不行的):
-
导入依赖
-
保留Dubbo 相关的xml配置文件
-
在启动类使用注解@ImportResource导入Dubbo的xml配置文件:
@ImportResource(locations="classpath:provider.xml")
-
这种情况下,就不需要注解(com.alibaba.dubbo.config.annotation.Service) 来暴漏服务了
第三种,使用 注解API的方式,可以实现方法级配置:
-
将每一个组件手动配置到容器中,让dubbo来扫描其他的组件
-
这种情况是需要注解(com.alibaba.dubbo.config.annotation.Service) 来暴漏服务了
-
在启动类中添加注解:@EnableDubbo(scanBasePackages = “com.wlw.dubbo”)
-
配置类
package com.wlw.dubbo.config; import java.util.ArrayList; import java.util.List; import com.wlw.dubbo.service.UserService; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.alibaba.dubbo.config.ApplicationConfig; import com.alibaba.dubbo.config.MethodConfig; import com.alibaba.dubbo.config.MonitorConfig; import com.alibaba.dubbo.config.ProtocolConfig; import com.alibaba.dubbo.config.ProviderConfig; import com.alibaba.dubbo.config.RegistryConfig; import com.alibaba.dubbo.config.ServiceConfig; @Configuration public class MyDubboConfig { //<dubbo:application name="boot-user-service-provider"></dubbo:application> @Bean public ApplicationConfig applicationConfig() { ApplicationConfig applicationConfig = new ApplicationConfig(); applicationConfig.setName("boot-user-service-provider"); return applicationConfig; } //<dubbo:registry protocol="zookeeper" address="127.0.0.1:2181"></dubbo:registry> @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="userServiceImpl01" timeout="1000" version="1.0.0"> <dubbo:method name="getUserAddressList" timeout="1000"></dubbo:method> </dubbo:service> */ @Bean public ServiceConfig<UserService> userServiceConfig(UserService userService){ ServiceConfig<UserService> serviceConfig = new ServiceConfig<>(); serviceConfig.setInterface(UserService.class); serviceConfig.setRef(userService); serviceConfig.setVersion("1.0.0"); //配置每一个method的信息 MethodConfig methodConfig = new MethodConfig(); methodConfig.setName("getUserAddressList"); methodConfig.setTimeout(1000); //将method的设置关联到service配置中 List<MethodConfig> methods = new ArrayList<>(); methods.add(methodConfig); serviceConfig.setMethods(methods); return serviceConfig; } //ProviderConfig //MonitorConfig }
-
启动类:
package com.wlw.dubbo; import com.alibaba.dubbo.config.spring.context.annotation.EnableDubbo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ImportResource; //@EnableDubbo //@ImportResource(locations = "classpath:provider.xml") @EnableDubbo(scanBasePackages = "com.wlw.dubbo") @SpringBootApplication public class BootUserServiceProviderApplication { public static void main(String[] args) { SpringApplication.run(BootUserServiceProviderApplication.class, args); } }
8、详细代码
详细代码:具体的配置操作,都是提交记录:wlw/dubboDemo (gitee.com)