之前我们简单介绍了dubbo配置服务提供者、消费者以及管理平台监控平台,接下来我们再说一下dubbo的其他配置。
dubbo可以在JVM 启动参数、dubboXML、dubbo.properties 三个地方配置相关属性,这里我们以端口为例.
-Ddubbo.protocol.port=20883
<dubbo:protocol name="dubbo" port="20882">dubbo:protocol>
dubbo.protocol.port=20881
JVM 启动 -D 参数优先,这样可以使用户在部署和启动时进行参数重写,比如在启动时需改变协议的端口。
XML 次之,如果在 XML 中有配置,则 dubbo.properties 中的相应配置项无效。
Properties 最后,相当于缺省值,只有 XML 没有配置时,dubbo.properties 的相应配置项才会生效,通常用于共享公共配置,比如应用名。
前面介绍了服务提供者接口的配置
当然我们只是把timeout
属性配置在了接口上,而接口中有那么多方法,所以我们还可以具体配置到方法
这样我们就指定了getUser
方法timeout
属性
但是服务提供者和消费者有那么多的接口一个一个配置岂不是太麻烦,所以我们可以将一样的配置抽取出来作为服务提供者以及消费者的缺省配置
以 timeout 为例,显示了配置的查找顺序,其它 retries, loadbalance, actives 等类似
其中,服务提供方配置,通过 URL 经由注册中心传递给消费方。
建议由服务提供方设置超时,因为一个方法需要执行多长时间,服务提供方更清楚,如果一个消费方同时引用多个服务,就不需要关心每个服务的超时设置。
Dubbo 缺省会在启动时检查依赖的服务是否可用,不可用时会抛出异常,阻止 Spring 初始化完成,以便上线时,能及早发现问题,默认 check=“true”。
可以通过 check=“false” 关闭检查,比如,测试时,有些服务不关心,或者出现了循环依赖,必须有一方先启动。
例子
当我们没有配置检查属性的时候.只启动消费者,可以看到控制台输出错误信息 No provider
我们配置启动检查check
为false
<dubbo:reference id="userService" interface="com.yz.dubbo.api.IUserService" check="false">dubbo:reference>
当我们设置check="false"
时,在没有提供者的情况下,消费者启动是不会报错的
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
new String[] { "classpath:customer.xml" });
final IUserService demoService = (IUserService) context.getBean("userService");
// System.out.println(demoService.getUser());
System.out.println("程序运行......");
System.in.read();
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
new String[] { "classpath:customer.xml" });
final IUserService demoService = (IUserService) context.getBean("userService");
System.out.println(demoService.getUser());
System.out.println("程序运行......");
System.in.read();
可以看到程序报错,就是显示调用 demoService.getUser()
这段代码导致的
注册中心检查
dubbo.registry.check=false
我们可以通过以上配置关闭服务提供者消费者对注册中心的检查,这样注册中心挂掉了,我们服务提供者消费者启动也不会报错,只是不能注册服务而已…
例子
当我们的注册中心挂掉的时候,我们启动服务消费者以及提供者是会报错的
我们只需要配置注册中心不检查,启动就不会报错而且当注册中心重新恢复的时候他们会自动的订阅服务以及注册服务
<dubbo:registry address="zookeeper://127.0.0.1:2181" check="false">dubbo:registry>
由于网络或服务端不可靠,会导致调用出现一种不确定的中间状态(超时)。为了避免超时导致客户端资源(线程)挂起耗尽,必须设置超时时间。
在现实的开发中我们往往一些服务提供者的调用比较耗时,而dubbo的timeout
缺省配置为1000
毫秒,也就是说当消费者调用服务提供者一秒钟还没有返回结果,则消费者会报错,如下
提供者
public class UserServiceImpl implements IUserService{
@Override
public List<User> getUser() throws UserException {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return Arrays.asList(new User[]{new User(1,"yz","china","hlj")
,new User(2,"zwl","china","ah")
,new User(3,"hhj","china","zj")});
}
}
可以看到消费者在等待一秒后还没有结果就报错,所以在线上我们可以通过设置timeout来避免提供者服务耗时带来的问题
<dubbo:service interface="com.yz.dubbo.api.IUserService" ref="userService1" timeout="4000">dubbo:service>
消费者在等待三秒后,提供者服务已经被正常调用
当我们服务消费者消费出现失败,可通过 retries="2"
来设置重试次数(不含第一次),多次调用服务提供者
例子
首先我们去掉之前的timeout
属性来模拟出错,并加上retries
来实现重试
<dubbo:reference id="userService" interface="com.yz.dubbo.api.IUserService" check="false" retries="3">dubbo:reference>
提供者
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("被调用了............");
return Arrays.asList(new User[]{new User(1,"yz","china","hlj")
,new User(2,"zwl","china","ah")
,new User(3,"hhj","china","zj")});
接下来我们分别启动服务提供者与消费者,可以看到,我们消费者在调用失败后提供者被调用了四次
当一个接口实现,出现不兼容升级时,可以用版本号过渡,版本号不同的服务相互间不引用。
可以按照以下的步骤进行版本迁移:
也就实现了dubbo所说的灰度发布
例子
首先我们创建提供者接口两个不同实现
UserServiceImpl
@Override
public List<User> getUser() throws UserException {
System.out.println("被调用了1............");
return Arrays.asList(new User[]{new User(1,"yz","china","hlj")
,new User(2,"zwl","china","ah")
,new User(3,"hhj","china","zj")});
}
UserServiceImpl2
@Override
public List<User> getUser() throws UserException {
System.out.println("被调用了2............");
return Arrays.asList(new User[]{new User(1,"yz","china","hlj")
,new User(2,"zwl","china","ah")
,new User(3,"hhj","china","zj")});
}
接下来在provider.xml
配置文件中提供者接口实现指向不同的两个类,并指定不同的版本
<bean id="userService1" class="com.yz.dubbo.impl.UserServiceImpl">bean>
<bean id="userService2" class="com.yz.dubbo.impl.UserServiceImpl2">bean>
<dubbo:service interface="com.yz.dubbo.api.IUserService" ref="userService1" version="1.0.0">dubbo:service>
<dubbo:service interface="com.yz.dubbo.api.IUserService" ref="userService2" version="2.0.0">dubbo:service>
在customer.xml
中指定消费者的版本号为1.0.0
<dubbo:reference id="userService" interface="com.yz.dubbo.api.IUserService" check="false" version="1.0.0">dubbo:reference>
在customer.xml
中指定消费者的版本号为2.0.0
<dubbo:reference id="userService" interface="com.yz.dubbo.api.IUserService" check="false" version="2.0.0">dubbo:reference>
可以看到了通过指定版本号分别调用了不同的接口实现,这样在实际开发中就能够实现新旧功能的过度