sentinel流控设置
sentinel降级的设置
对应soul中sentinel插件的设置
规则说明:
流控:
是否开启流控(1或0) :是否开启sentinel的流控
阈值类型 : QPS 或线程数
流控效果 : 快速失效、Warm Up、排队等待
单机阈值 : 设置单机阈值数熔断:
是否开启熔断(1或0) :是否开启sentinel熔断。
熔断降级策略: RT、异常比例、异常数
熔断阈值:阈值(RT数值)
熔断时间窗口: 降级的时间,单位为 s。
熔断URI: 熔断后的降级uri
SentinelPlugin源码解析
请求进入到SentinelPlugin
的核心方法doExecute
@Override
protected Mono<Void> doExecute(final ServerWebExchange exchange, final SoulPluginChain chain, final SelectorData selector, final RuleData rule) {
final SoulContext soulContext = exchange.getAttribute(Constants.CONTEXT);
assert soulContext != null;
// 资源名(选择ID_规则名称),sentinel通过资源名来控制限流熔断
String resourceName = SentinelRuleHandle.getResourceName(rule);
// 获取限流降级规则对象
SentinelHandle sentinelHandle = GsonUtils.getInstance().fromJson(rule.getHandle(), SentinelHandle.class);
// SentinelReactorTransformer:对流控和熔断进行 响应式监控
return chain.execute(exchange).transform(new SentinelReactorTransformer<>(resourceName)).doOnSuccess(v -> {
// 处理成功,放行
// 处理出错,输出错误
if (exchange.getResponse().getStatusCode() != HttpStatus.OK) {
HttpStatus status = exchange.getResponse().getStatusCode();
exchange.getResponse().setStatusCode(null);
throw new SentinelFallbackException(status);
}
}).onErrorResume(throwable -> sentinelFallbackHandler.fallback(exchange, UriUtils.createUri(sentinelHandle.getFallbackUri()), throwable));
}
此方法做了如下操作:
1)将后台设置的降级规则转为SentinelHandle
对象
@Getter
@Setter
@EqualsAndHashCode
public class SentinelHandle {
// 是否启用流控
private Integer flowRuleEnable = Constants.SENTINEL_ENABLE_FLOW_RULE;
// 阈值类型
private Integer flowRuleGrade = Constants.SENTINEL_QPS_FLOW_GRADE;
// 单机阈值
private Integer flowRuleCount;
// 流控效果(快速失效、Warm Up、排队等待)
private Integer flowRuleControlBehavior = Constants.SENTINEL_FLOW_REJECT;
// 是否启用熔断降级
private Integer degradeRuleEnable = Constants.SENTINEL_ENABLE_DEGRADE_RULE;
// 降级策略(RT、异常比例、异常数)
private Integer degradeRuleGrade = Constants.SENTINEL_RESPONSE_RULE_GRADE;
// RT数
private Integer degradeRuleCount;
// 时间窗口
private Integer degradeRuleTimeWindow;
// 自定义异常路径
private String fallbackUri;
}
2)获取资源名,对该资源进行降级规则设置处理
资源名:选择ID_规则名称
使用com.alibaba.csp.sentinel.adapter.reactor.SentinelReactorTransformer对该资源进行流控、熔断的设置处理
// SentinelReactorTransformer:对流控和熔断进行 响应式监控
return chain.execute(exchange).transform(new SentinelReactorTransformer<>(resourceName)).doOnSuccess(v -> {
// 处理成功,放行
// 处理出错,输出错误
if (exchange.getResponse().getStatusCode() != HttpStatus.OK) {
HttpStatus status = exchange.getResponse().getStatusCode();
exchange.getResponse().setStatusCode(null);
throw new SentinelFallbackException(status);
}
}).onErrorResume(throwable -> sentinelFallbackHandler.fallback(exchange, UriUtils.createUri(sentinelHandle.getFallbackUri()), throwable));
如果出错:调用SentinelFallbackHandler
的fallback
方法
default Mono<Void> fallback(ServerWebExchange exchange, URI uri, Throwable t) {
if (Objects.isNull(uri)) {
return generateError(exchange, t);
}
DispatcherHandler dispatcherHandler = SpringBeanUtils.getInstance().getBean(DispatcherHandler.class);
ServerHttpRequest request = exchange.getRequest().mutate().uri(Objects.requireNonNull(uri)).build();
ServerWebExchange mutated = exchange.mutate().request(request).build();
return dispatcherHandler.handle(mutated);
}
先判断是否有熔断后的降级uri处在(后台设置),如果不存在,调用generateError
方法,否则调用uri返回错误信息
generateError
方法的处理
public Mono<Void> generateError(final ServerWebExchange exchange, final Throwable throwable) {
Object error;
// 降级
if (throwable instanceof DegradeException) {
exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
error = SoulResultWrap.error(SoulResultEnum.SERVICE_RESULT_ERROR.getCode(), SoulResultEnum.SERVICE_RESULT_ERROR.getMsg(), null);
} else if (throwable instanceof FlowException) { // 限流
exchange.getResponse().setStatusCode(HttpStatus.TOO_MANY_REQUESTS);
error = SoulResultWrap.error(SoulResultEnum.TOO_MANY_REQUESTS.getCode(), SoulResultEnum.TOO_MANY_REQUESTS.getMsg(), null);
} else if (throwable instanceof BlockException) { // 阻塞
exchange.getResponse().setStatusCode(HttpStatus.TOO_MANY_REQUESTS);
error = SoulResultWrap.error(SoulResultEnum.SENTINEL_BLOCK_ERROR.getCode(), SoulResultEnum.SENTINEL_BLOCK_ERROR.getMsg(), null);
} else {
return Mono.error(throwable);
}
return WebFluxResultUtils.result(exchange, error);
}
此方法是针对降级、限流、阻塞的默认处理。
此致,整个请求结束,进行到下一个插件
流控验证
设置如下:
正常访问:
快速点两下: