降级的概念

降级的作用就是当某个服务的访问量急剧增高,服务器资源不够用时,将访问量较低的服务停下来,把服务器资源让给资源需求较高的服务,以避免整个系统宕掉

降级的实现两种实现方式

  1. 利用 Docker 来实现,当需要对某个服务进行降级时,直接将这个服务所有的容器停掉,需要恢复的时候重新启动就可以了
  2. 在网关中实现降级,某个服务被降级后,前台在请求被降级服务的接口时直接拒绝掉

1.在zuul网关中实现降级

1、在zuul网关的application.yml中,配置要降级的服务

将要降级的服务配置到down.service节点,多个服务之间用逗号分隔

down: # 配置需要降级的服务,多个服务之间用逗号分隔
  service: jwxt-student,jwxt-xxxx
2、在zuul服务中创建新的filter过滤器,配置降级

过滤器拦截到接口后,找到接口所属的服务,若此接口的服务在down的service节点中存在,那么对该服务进行降级处理

概括:

  1. 从application.yml配置文件中获取down.service节点的值(要降级的服务)
  2. 将过滤器的拦截规则设置为路由拦截
  3. 在run()方法中创建当前上下文对象;从上下文中获取当前接口的服务的实例;若此服务在down.service节点中存在,则对此服务进行降级(拒绝服务)并停止该服务的zuul拦截器;在上下文中设置名为isSuccess的参数,动态控制过滤器的启动与停止;最后向前台返回服务降级提示(注意:向前台返回提示时,必须设置编码格式)
  4. 在shouldFilter()方法中通过上下文中的isSuccess判断是否开启过滤器
@Component
public class DownFilter extends ZuulFilter {

    @Value("${down.service}")//从配置文件中获取down.service节点的值
    private String BASIC_CONF;

    public DownFilter(){
        super();
    }

    @Override
    public String filterType() {
        return FilterConstants.ROUTE_TYPE;//过滤器的拦截规则
    }

    @Override
    public int filterOrder() {
        return 0; //过滤的优先级
    }

    @Override
    public boolean shouldFilter() {//是否开启过滤器
        //从RequestContext中获取isSuccess,判断如果isSuccess存在,那么说明服务需要被降级,返回false,
        // 如果isSuccess不存在,那么该服务不需要被降级,返回true
        Object success = RequestContext.getCurrentContext().get("isSuccess");
        return success == null ? true : Boolean.parseBoolean(success.toString());
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext context = RequestContext.getCurrentContext();
        context.getResponse().setContentType("application/json;charset=utf-8");
        Object serviceId = context.get("serviceId");//从上下文中获取当前访问的接口的服务的实例
        if(serviceId != null && BASIC_CONF != null){
            List<String> serviceIds = Arrays.asList(BASIC_CONF.split(","));//将BASIC_CONF的值通过 , 分隔存入list集合
            if(serviceIds.contains(serviceId.toString())){//然后判断若服务的id在serviceIds中包含,那么就降级这个服务
                context.setSendZuulResponse(false);//拒绝服务
                context.set("isSuccess",false);//动态的控制过滤器的启动停止

                Result result = new Result(ResultCode.FAIL);//向前台返回降级提示(这里没有写降级提示)
                context.setResponseBody(JSON.toJSONString(result));//setResponseBody设置返回的内容
                return null;
            }
        }
        return null;
    }
}