文章目录
- 什么是服务降级?
- 如何实现服务降级
- 测试
- 进阶
什么是服务降级?
当服务器压力比较大的时候,我们可以通过服务降级,屏蔽掉一些非关键服务,给它们定义一个降级后的返回策略,从而降低核心业务的压力。
通俗的说,服务降级就是在远程调用失败(例如超时)之后,直接采用降级措施,返回一个我们已经定义好的提示。例如,在12306抢票高峰时,明明票还有,但查询列表总是空的,过了高峰之后再次查询,又会恢复正常,这可能是因为超时或者网络问题导致查询失败,最后不得不采用了服务降级进行处理,给我们返回一个已经定义好的值。
如何实现服务降级
Dubbo 中有一个 mock 的配置,我们可以通过这个配置实现服务降级。其中,mock 的配置有两种:
- 通过 boolean 值指定是否实行服务降级,其中默认为 false,当配置为 true 时,缺省通过在服务名后面加上 Mock 后缀的类来指定降级后的返回值
- 直接 return null,统一返回空
需要注意的是,mock 只会在非业务异常的时候执行,比如超时,又或者是网路异常。
测试
首先我们来看一下不做服务降级会是什么后果,我们在服务提供者中故意令其超时,由于 Dubbo 默认超时时间为1s,我们就令其睡眠两秒,代码如下:
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) {
//让其超时
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "远程调用的值:" + name;
}
}
然后运行服务提供者与服务消费者,果不其然,直接报错。
然后我们添加 return null 的降级设置,代码如下,看看其效果
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(mock = "return null")
NameService nameService;
@Override
public String change(String name) {
return nameService.updateName(name);
}
}
显然它会直接返回空,这需要我们做进一步的处理。需要注意的是,当我们将 mock 设置为 return null 时,它不会进行远程调用,而是直接返回一个空就行了。
在某些情况下,直接返回空对我们的用户不太友好,这时我们可以给用户返回一个我们之前定义好的值。首先我们在 api 模块中指定一个服务降级的处理策略,其中这个处理类名缺省为在服务名上加上 Mock 后缀,且应该与服务接口在同路径下。
package edu.szu.api.service;
public class NameServiceMock implements NameService {
//定义服务降级的返回值
@Override
public String updateName(String name) {
return "服务降级了!";
}
}
然后在消费者中配置 mock 属性为 true。
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(mock = "true")
NameService nameService;
@Override
public String change(String name) {
return nameService.updateName(name);
}
}
然后我们发起一次远程调用,由于调用超时,显然是失败的,但由于我们进行了服务降级,会返回我们指定的返回值。
另外,该方法与直接 return null 不同的是,如果我们的远程调用成功了,不会执行服务降级,会返回远程调用的结果,而 return null 事实上根本不进行远程调用就直接返回空了。
进阶
当然,我们也可以通过 Admin 控制台来实现服务降级。
我们发现对服务可以进行屏蔽与容错操作,其中,屏蔽表示对服务不发起远程调用,直接返回空就行了;而容错则表示在对该服务的方法调用失败后,再返回空,这两个是不同的。