一、降级概念
当服务的访问量剧增,服务就可能出想问题,所以就需要作出一些处理,比如服务降级。(例:某电商网站在搞活动时,活动期间压力太大,如果再进行下去,整个系统有可能挂掉,
这个时候可以释放掉一些资源,将一些不那么重要的服务采取降级措施,
比如登录、注册。登录服务停掉之后就不会有更多的用户抢购,
同时释放了一些资源,登录、注册服务就算停掉了也不影响商品抢购。)
二、实现方式
- 利用docker实现。当需要某个服务进行降级时,直接将这个服务所有的容器关掉,需要恢复的时候重启就可以了。
- 在api网关层进行处理,当某个服务呗降级了,前段的请求就直接拒绝掉,不想内部服务转发,将流量挡回去。
– 我们这里主要实现一下api网关对服务的降级实现。
实现思路
- 主要逻辑在过滤器的 run 方法中,通过 RequestContext 获取即将路由的服务 ID,
通过配置信息获取降级的服务信息,如果当前路由的服务在其中,就直接拒绝,
返回对应的信息让客户端做对应的处理。 - 当需要降级的时候,直接在 springcloud config 的后台改一下配置就可以马上生效,
当然也可以做成自动的,比如监控某些指标,流量、负载等,
当达到某些指标后就自动触发降级。
四、代码实现
zuul
application.yml
down:
service: jwxt-learner //需要降级的服务
filter.java
package com.jwxt.filter;
import com.alibaba.fastjson.JSON;
import com.jwxt.response.Result;
import com.jwxt.response.ResultCode;
import com.jwxt.utils.JSONUtils;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.bouncycastle.asn1.ocsp.ResponseData;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
@Component
public class DownFilter extends ZuulFilter {
//获取yml中要降级的服务名
@Value("${down.service}")
private String BASIC_CONF;
public DownFilter(){
super();
}
//拦截方式
@Override
public String filterType() {
return FilterConstants.ROUTE_TYPE; //route
}
//拦截优先级
@Override
public int filterOrder() {
return 1;
}
//触发条件
@Override
public boolean shouldFilter() {
Object success = RequestContext.getCurrentContext().get("isSuccess");
return success == null ? true : Boolean.parseBoolean(success.toString());
}
//进行服务降级
@Override
public Object run() throws ZuulException {
//获取请求
RequestContext context = RequestContext.getCurrentContext();
Object serviceId = context.get("serviceId");
/**
*判断该请求是否是被降级服务中的去请求,若成立将直接响应,不在请求该服务
*/
if(serviceId != null && BASIC_CONF != null){
List<String> serviceIds = Arrays.asList(BASIC_CONF.split(","));
if(serviceIds.contains(serviceId.toString())){
context.setSendZuulResponse(false);
context.set("isSuccess",false);
Result result = new Result(ResultCode.SERVICE_IS_DOWN);
context.setResponseBody(JSON.toJSONString(result));
context.getResponse().setContentType("application/json;charset=utf-8");
return null;
}
}
return null;
}
}
如果登录的用户需要使用learner服务,则访问不可达
- 前台响应为