建议看这篇文章是在学习了快速入门 dubbo 那篇文章的基础上来学习
文档地址 https://dubbo.apache.org/zh/index.html
关于 dubbo 的配置说明 在文档中都有比较详细的说明,下面举例的都是较为常用的
直接启动这个测试类,注意 spring 配置文件的位置
/**
* @author : look-word
* 2022-07-19 09:44
**/
public class TestCheckException {
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring/spring.xml");
// 让程序一直读取, 目的是不让他停止
System.in.read();
}
}
当我们启动后会发现,诶,怎么没有错误呢,是下面 log4j 的提示呢?
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
再次启动,会发现。如我们所愿它出错了。
错误信息
java.lang.IllegalStateException: Failed to check the status of the service service.HelloService. No provider available for the service service.HelloService from the url zookeeper:
在 spring.xml 配置文件中加上就不会有异常提示了
<!--默认是true:抛异常;false:不抛异常-->
<dubbo:consumer check="false" />
然后启动测试文件即可,这里不做演示了
<!--设置超时时间为2秒,默认为1秒-->
<dubbo:provider timeout="2000"/>
@com.alibaba.dubbo.config.annotation.Service
public class HelloServiceImpl implements HelloService {
@Override
public String sayHello(String name) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return "Hello," + name + "!!!";
}
}
错误代码: com.alibaba.dubbo.remoting.TimeoutException: Waiting server-side response timeout.
配置原则:
dubbo 推荐在Provider上尽量多配置Consumer端属性
:
服务的提供者
,比服务使用方更清楚服务性能参数
,如调用的超时时间
,合理的重试
次数,等等在Provider配置后
,Consumer不配置
则会使用 Provider 的配置值,即 Provider 配置可
以作消费者的缺省值<!-- 消费方连接第1次不算,再来重试3次,总共重试4次 -->
<dubbo:provider timeout="2000" retries="3"/>
修改实现类代码: 增加次数
@com.alibaba.dubbo.config.annotation.Service
public class HelloServiceImpl implements HelloService {
int a;
@Override
public String sayHello(String name) {
System.out.println("被调用第"+(++a)+"次");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return "Hello," + name + "!!!";
}
}
可以看到 重试了 3 次 第一次不算
并不是所有的方法都适合设置重试次数
我们需要单独为某个方法设置重试次数
public interface HelloService {
String sayHello(String name);
String no();
}
@com.alibaba.dubbo.config.annotation.Service
public class HelloServiceImpl implements HelloService {
int a,b;
@Override
public String sayHello(String name) {
System.out.println("sayHello被调用第"+(++a)+"次");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return "Hello," + name + "!!!";
}
@Override
public String no() {
System.out.println("no被调用第"+(++b)+"次");
return "no";
}
}
public interface HelloService {
String sayHello(String name);
String no();
}
@RestController
public class HelloAction {
// Resource 注解 指定名称注入
@Resource(name = "helloService")
private HelloService hs;
@RequestMapping("hello/{name}")
@ResponseBody
public String hello(@PathVariable String name) {
return hs.sayHello(name);
}
@RequestMapping("no")
@ResponseBody
public String no() {
return hs.no();
}
}
<dubbo:reference interface="service.HelloService" id="helloService">
<dubbo:method name="sayHello" retries="3"/>
<dubbo:method name="no" retries="0"/>
</dubbo:reference>
启动项目,访问
可以看到,我们为每种方法配置的重试次数成功了
为 HelloService 定义了两个版本
<dubbo:service interface="service.HelloService" class="service.impl.HelloServiceImpl1" version="1.0.0">
</dubbo:service>
<dubbo:service interface="service.HelloService" class="service.impl.HelloServiceImpl2" version="2.0.0">
</dubbo:service>
注意
:消费者的控制层要改为自动注入,因为@Reference 注解和 dubbo:reference在这里冲突
启动测试
注意 每次修改配置文件 都需要重启项目
访问: http://localhost:8002/no
为什么要有本地存根?
先在消费者处理一些业务逻辑,再调用提供者的过程,就是“本地存根”
代码实现肯定在 消费者,创建一个 HelloServiceStub 类并且实现 HelloService 接口
注意:必须使用构造方法的方式注入
public class HelloServiceStub implements HelloService {
private HelloService helloService;
// 注入HelloService
public HelloServiceStub(HelloService helloService) {
this.helloService = helloService;
}
@Override
public String sayHello(String name) {
System.out.println("本地存根数据验证。。。");
if(!StringUtils.isEmpty(name)){
return helloService.sayHello(name);
}
return "i am sorry!";
}
@Override
public String no() {
return helloService.no();
}
}
<dubbo:reference interface="service.HelloService" id="helloService" version="*" stub="service.impl.HelloServiceStub">
<dubbo:method name="sayHello" retries="3"/>
<dubbo:method name="no" retries="0"/>
</dubbo:reference>
老样子,clean项目 然后打包启动
<dubbo:provider timeout="2000" retries="3" port="20881"/>
HelloServiceImpl2 类,服务器 1,服务器 2,服务器 3
启动一个消费者,三个提供者
<dubbo:reference loadbalance="roundrobin" interface="service.HelloService" id="helloService" version="2.0.0" stub="service.impl.HelloServiceStub">
<dubbo:method name="sayHello" retries="3"/>
<dubbo:method name="no" retries="0"/>
</dubbo:reference>
然后启动测试即可