dubbo的基本配置还有一些,本文逐一来攻克

一、超时机制

如果没有超时机制,那么服务提供者一旦出现问题,十几秒才给响应,服务消费者线程大量阻塞等待,就会造成很大的问题,因此,超时时间的配置一定是dubbo考虑的问题。

image

其中,服务提供方配置,这个时间是指通过 URL 经由注册中心传递给消费方。

如何配置,这张图说明了,优先级是从上往下依次下降。也就是说,有两大原则:

  • 方法级优先,接口级次之,全局配置再次之。
  • 如果级别一样,则消费方优先,提供方次之。

其它 retries, loadbalance, actives 等类似。并且dubbo默认有一个超时时间就是1000ms

(建议由服务提供方设置超时,因为一个方法需要执行多长时间,服务提供方更清楚,如果一个消费方同时引用多个服务,就不需要关心每个服务的超时设置)。

springboot中配置差不多,形如:@Service(timeout = 3000).但是对于这种方式我们似乎不能再精确到方法级别上了。

二、重试机制

写法与上面的timeout类似,就是retries="3"表示默认的连接依次之外,如果出现意外还可以再次连接三次,那么总次数就是4次。

当服务的提供方有多台呢?那么就会去一台一台地试而不是在一棵树上吊死。

额外需要注意的一点使重试机制不能放在非幂等的接口上。

springboot中配置差不多,形如@Service(retries = 3)

三、多版本

当一个接口实现,出现不兼容升级时,可以用版本号过渡,版本号不同的服务相互间不引用。

可以按照以下的步骤进行版本迁移:

在低压力时间段,先升级一半提供者为新版本
再将所有消费者升级为新版本
然后将剩下的一半提供者升级为新版本
老版本服务提供者配置:

1
<dubbo:service interface="com.foo.BarService" version="1.0.0" />

新版本服务提供者配置:

1
<dubbo:service interface="com.foo.BarService" version="2.0.0" />

老版本服务消费者配置:

1
<dubbo:reference id="barService" interface="com.foo.BarService" version="1.0.0" />

新版本服务消费者配置:

1
<dubbo:reference id="barService" interface="com.foo.BarService" version="2.0.0" />

如果不需要区分版本,随机选择一个都行,可以按照以下的方式配置:

1
<dubbo:reference id="barService" interface="com.foo.BarService" version="*" />

springboot中配置差不多,形@Service(version = "1.0")

四、三种方式整合springboot

我们之前整合springboot的方式是:引入dubbo-starter,在application.properties文件中配置属性,用@Service暴露服务,用@Reference来使用服务。最后用@EnableDubbo来启动dubbo功能。这个注解点进去看是:

1
2
3
4
5
6
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@EnableDubboConfig
@DubboComponentScan

包含了包扫描的功能。这种自动扫描包可以换成在配置文件中指定扫描位置:dubbo.scan.base-packages=xxx即可。

现在我们遇到一个问题,就是传统的xml可以做到精确的方法级别的配置,但是上一种方式是无法做到的,那么如何才能做到对方法级别的控制呢?

其实我们还是可以将传统的xml文件拷贝到我们的resources文件夹下,一个字都不用动,只需要将@EnableDubbo注解以及暴露服务用的@Service都注释掉,换成:@ImportResource(locations="classpath:provider.xml")即可。我们来改造之前的provider-service:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?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://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

<!-- 1、指定当前服务/应用的名字(同样的服务名字相同,不要和别的服务同名) -->
<dubbo:application name="provider-service">
</dubbo:application>

<!-- 2、指定注册中心的位置 -->
<!-- <dubbo:registry address="zookeeper://127.0.0.1:2181"></dubbo:registry> -->
<dubbo:registry protocol="zookeeper" address="127.0.0.1:2181"/>

<!-- 3、指定通信规则(通信协议?通信端口) -->
<dubbo:protocol name="dubbo" port="20880"/>

<!-- 4、暴露服务 ref:指向服务的真正的实现对象 -->
<dubbo:service interface="com.njupt.swg.DemoService"
ref="demoService" version="1.0.0">
<dubbo:method name="sayHello" timeout="1000"/>
</dubbo:service>

<!-- 服务的实现 -->
<bean id="demoService" class="com.njupt.swg.service.DemoServiceImpl"/>


<!-- 连接监控中心 -->
<dubbo:monitor protocol="registry"/>

</beans>

在版本<dubbo.starter.version>0.2.1.REALEASE</dubbo.starter.version><dubbo.version>2.6.5</dubbo.version>中一直报错,莫名其妙,无奈我降级为<dubbo.starter.version>0.2.0</dubbo.starter.version><dubbo.version>2.6.2</dubbo.version>启动成功。这个代码存放在2.6.2分支代码中。

这是第二种方式。我们引入的话虽说是完美融合了两者,但是作为一个springboot使用者,再用回去好像很奇怪,本来就是为了免去注解,但是这个时候又引入注解,搞成了四不像。下面就要介绍第三种方式了,就是注解的方式,简单来说就是用一个config来代替这个xml中所有的标签。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Configuration
public class MyConfig {
@Bean
public ApplicationConfig applicationConfig(){
ApplicationConfig config = new ApplicationConfig();
config.setName("provider-service");
return config;
}

@Bean
public RegistryConfig registryConfig(){
RegistryConfig config = new RegistryConfig();
config.setProtocol("zookeeper");
config.setAddress("127.0.0.1:2181");
return config;
}
}

其他的配置都同理,这样在spring容器启动的时候就自动把这些配置加载进来,达到了相同的效果。这里我嫌麻烦就没去验证。其中方法级的配置,对应的xml是:

1
2
3
4
<dubbo:service interface="com.njupt.swg.DemoService"
ref="demoService" version="1.0.0">
<dubbo:method name="sayHello" timeout="1000"/>
</dubbo:service>

如何改写呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
@Bean
public ServiceConfig<DemoService> demoServiceConfig(DemoService demoService){
ServiceConfig<DemoService> config = new ServiceConfig<>();
config.setInterface(DemoService.class);
config.setRef(demoService);
//配置方法信息
MethodConfig methodConfig = new MethodConfig();
methodConfig.setName("sayHello");
methodConfig.setTimeout(1000);
//method放到ServiceConfig中
config.setMethods(Arrays.asList(methodConfig));
return config;
}

这就完成了手动注册的功能,就是第三种实现方式。