重试
什么是重试
重试就是在调用失败时,会再次调用,如果在配置的调用次数内都失败,则认为此次请求异常,会抛出一个异常。
Dubbo 在调用服务失败后,会默认重试两次。Dubbo 的路由机制确保会将超时的请求路由到其他机器上,而不是本机重试,所以 Dubbo 的重试机制也能一定程度的保证服务的质量。
测试
我们先将服务提供者修改一下,故意让其超时,然后运行 producer 和 consumer 两个模块。
package edu.szu.producer.serviceImpl;
import com.alibaba.dubbo.config.annotation.Service;
import edu.szu.api.service.NameService;
import org.springframework.stereotype.Component;
@Component
@Service
public class NameServiceImpl implements NameService {
@Override
public String updateName(String name) {
System.out.println("updateName 函数开始运行");
//故意让其超时
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "修改后的名称:" + name;
}
}
在浏览器输入 http://localhost:8081/change/HelloDubbo ,远程调用服务提供者提供的服务,结果如下:
在服务提供者的输出中我们可以发现这个函数确实被调用了三次,证明除了一开始的第一次调用之外,还重试了两次,即重试机制的默认缺省值为2次。
然后我们修改一下重试次数,在消费者的配置中将其修改为1次。
#设置重试次数为1次
dubbo.consumer.retries=1
再次启动两个模块,可以发现,函数只执行了两次(初始一次+重试一次),证明我们的重试设置生效了。
注意
只有在幂等方法上才能使用重试机制,在非幂等方法上不能使用重试。那么,什么是幂等方法呢?其实,只要多次运行方法所产生的最终效果是一致的,就可以被称为幂等方法。
本地存根
什么是本地存根
在消费者远程调用服务提供者的服务实现之前,如果我们需要做一些参数验证、缓存、小功能之类的,需要满足要求再调用服务提供者提供的远程服务,这个功能可以通过本地存根来实现。
我们可以将本地存根理解为预处理信息。本地存根可以在提供者中实现,也可以在消费者中实现,如果在消费者中已经实现了本地存根,那么提供者的将不起作用。
实现
我们选择在 api 层开发本地存根
编写本地存根代码
package edu.szu.api.serviceStub;
import edu.szu.api.service.NameService;
public class NameServiceStub implements NameService {
private final NameService nameService;
// 构造函数传入真正的远程代理对象
public NameServiceStub(NameService nameService){
this.nameService = nameService;
}
@Override
public String updateName(String name) {
System.out.println("执行本地存根");
try {
if(name.equals("Tony")) return "返回一个本地存根";
return nameService.updateName(name);
} catch (Exception e) {
return "返回一个本地存根";
}
}
}
然后我们需要在消费者中指定本地存根的路径,一个本地存根的功能就实现了。
package edu.szu.consumer.serviceImpl;
import com.alibaba.dubbo.config.annotation.Reference;
import edu.szu.api.service.NameService;
import edu.szu.consumer.service.ChangeService;
import org.springframework.stereotype.Component;
@Component
public class ChangeServiceImpl implements ChangeService {
//指定本地存根
@Reference(stub = "edu.szu.api.serviceStub.NameServiceStub")
NameService nameService;
@Override
public String change(String name) {
return nameService.updateName(name);
}
}
测试
我们首先在浏览器中输入 http://localhost:8081/change/Tony,远程调用服务提供者提供的服务,结果如下:
在控制台显示如下:
显然我们的本地存根生效了。