启动时会在注册中心检查依赖的服务是否可用,不可用时会抛出异常
在消费方编写初始化容器的main方法启动(tomcat启动方式,必须访问一次action才能初始化spring)
/**
* @Program: dubbo_test2
* @Author: XiaoXing
* @Create: 2021-01-16 13:35
* @Description: 启动时检查
**/
public class TestCheckException {
public static void main(String[] args) {
//初始化spring
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring/spring.xml");
try {
System.in.read();
} catch (IOException e) {
e.printStackTrace();
}
}
}
<dubbo:consumer check="false" />
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %m%n
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=dubbo.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %l %m%n
log4j.rootLogger=error, stdout,file
由于网络或服务端不可靠,会导致调用过程中出现不确定的阻塞状态(超时)
为了避免超时导致客户端资源(线程)挂起耗尽,必须设置超时时间
在服务提供者添加如下配置:
<dubbo:provider timeout="2000"/>
可以将服务实现HelloServiceImpl.java中加入模拟的网络延迟进行测试:
@Service
public class HelloServiceImpl implements HelloService {
@Override
public String sayHello(String name) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Hello " + name + " !!!";
}
}
超时设置2秒,而模拟的网络延迟有3秒,超出时限,报错!
配置原则:
当出现失败,自动切换并重试其它服务器,dubbo重试的缺省值是2次,我们可以自行设置
在provider提供方配置:
<dubbo:provider timeout="2000" retries="3"/>
@Service
public class HelloServiceImpl implements HelloService {
@Override
public String sayHello(String name) {
System.out.println("被调用1次");
try {
//模拟网络延迟
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Hello " + name + " !!!";
}
}
并不是所有的方法都适合设置重试次数
单独设置某个方法
public interface HelloService {
public String sayHello(String name);
public String sayNo();
}
@Override
public String sayNo() {
System.out.println("------------no--------------");
return "no";
}
消费方接口添加sayNo()方法声明
public interface HelloService {
String sayHello( String name );
public String sayNo();
}
@Controller
public class HelloAction {
// @Reference // 远程去服务方将service的实现类注入进来
@Autowired
private HelloService helloService;
@RequestMapping("/hello")
@ResponseBody
public String sayHi(String name){
System.out.println(name);
return helloService.sayHello(name);
}
@RequestMapping("/no")
@ResponseBody
public String sayNo(){
return helloService.sayNo();
}
}
消费方配置方法重试次数
<dubbo:reference interface="service.HelloService" id="helloService">
<dubbo:method name="sayHello" retries="3">dubbo:method>
<dubbo:method name="sayNo" retries="0">dubbo:method>
dubbo:reference>
一个接口,多个(版本的)实现类,可以使用定义版本的方式引入
为HelloService接口定义两个实现类,提供者修改配置:
<dubbo:service interface="service.HelloService" class="service.impl.HelloServiceImpl01" version="1.0.0">dubbo:service>
<dubbo:service interface="service.HelloService" class="service.impl.HelloServiceImpl02" version="2.0.0">dubbo:service>
消费者就可以根据version的版本,选择具体的服务版本
<dubbo:reference interface="service.HelloService" id="helloService" version="1.0.0">
<dubbo:method name="sayHello" retries="3">dubbo:method>
<dubbo:method name="sayNo" retries="0">dubbo:method>
dubbo:reference>
注意:消费者的控制层要改为自动注入,因为@Reference注解和 dubbo:reference在这里冲突
@Controller
public class HelloAction {
// @Reference // 远程去服务方将service的实现类注入进来
@Autowired
private HelloService helloService;
}
当消费者的版本修改为 version="*",那么就会随机调用服务提供者的版本
目前我们的分布式架构搭建起来有一个严重的问题,就是所有的操作全都是 消费者发起,由服务提供者执行
消费者动动嘴皮子却什么活都不干,这样会让提供者很累,例如简单的参数验证,消费者完全能够胜任,把合法的参数再发送给提供者执行,效率高了,提供者也没那么累了
例如:去房产局办理房屋过户,请带好自己的证件和资料,如果什么都不带,那么办理过户手续会很麻烦,得先调查你有什么贷款,有没有抵押,不动产证是不是你本人,复印资料等操作。一天肯定办不完。明天还要来。如果你能提前将这些东西准备好,办理过户,1个小时足矣,这就是“房产中介办事效率高的原因”
话不多说,先在消费者处理一些业务逻辑,再调用提供者的过程,就是“本地存根”
代码实现肯定在 消费者,创建一个HelloServiceStub类并且实现HelloService接口
注意:必须使用构造方法的方式注入
public class HelloServiceStub implements HelloService {
private HelloService helloService;
//本地存根必须以构造方法的形式注入
public HelloServiceStub(HelloService helloService){
this.helloService = helloService;
}
@Override
public String sayHello(String name) {
if (!StringUtils.isEmpty(name)){
return helloService.sayHello(name);
}
return "i am sorry!";
}
@Override
public String sayNo() {
return helloService.sayNo();
}
}
修改消费者配置
<dubbo:reference interface="service.HelloService" id="helloService" version="2.0.0" stub="stub.HelloServiceStub">
<dubbo:method name="sayHello" retries="3">dubbo:method>
<dubbo:method name="sayNo" retries="0">dubbo:method>
dubbo:reference>