1.背景:
当系统流量剧增访问压力特别大的时候,我们需要对服务进行降级,可以限制甚至拒绝某个用户访问,也可以针对整个系统进行服务降级。我们采用的是全局服务降级。同时这些配置应该动态的而不是写死在应用程序中。遵循:数据库-->应用-->默认值这样的规律。在我们的管理后台进行监控系统。
2.首先我们配置一下参数:
(1).切流量后跳转的页面:
(2)限定某资源的访问频率
(3)禁止某些url访问
public class ServiceDegarding {
private static Logger log = LoggerFactory.getLogger(ServiceDegarding.class);
public static boolean isAllowed(String url) {
// 是否为不允许访问的url
Set<String> notAllowedUrlSet = GlobalConfig.getSetValue(GlobalConfigKey.NOT_ALLOWED_URLS);
if (notAllowedUrlSet.contains(url)) {
log.info("service degarding, not allowed to visit url:{}", url);
return false;
}
// 是否为切指定流量访问的url
Map<String, String> percentAllowedUrlMap = GlobalConfig.getMapValue(GlobalConfigKey.PERCENT_ALLOWED_URLS);
if (percentAllowedUrlMap.containsKey(url)) {
String v = percentAllowedUrlMap.get(url);
int percent = 10; // 如果设置了切部分流量, 默认开放10%的流量, 配置出错时使用这个值
if (!StringUtils.isNumeric(v)) {
log.error("service degarding with percent setting error, url:{}, v:{}", v);
} else {
percent = Integer.parseInt(v);
}
percent = Math.min(percent, 100);
int random = Math.abs(new Random().nextInt()) % 100;
log.info("service degarding with percent, url:{}, percent;{}, random:{}", url, percent, random);
return random < percent;
}
return true;
}
}
3.使用:
我们通过filter过滤器来加入限流:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
String servletPath = req.getServletPath();
// 系统降级处理,false表示限流了,跳转到限流页面
if (!ServiceDegarding.isAllowed(servletPath)) {
Map requestMap = request.getParameterMap();
log.info("{} service degarding. parameter:{}", servletPath, JsonMapper.obj2String(requestMap));
serviceDegardingPage(req, resp);
return;
}
chain.doFilter(req, resp);
return;
}