利用断路器状态统计sentinel熔断次数
2023-12-13 21:40:11
最近项目需要sentinel熔断时记录熔断的次数,在经过一阵搜索后决定利用断路器的状态变化来实现此功能
然而,遇到了这样的一个情况,断路器的状态在第一次熔断时正常从close–>open,但在后续(熔断时间内blocked或者熔断结束后重新开启断路器)断路器的状态变化均为half open–>open,导致无法区分究竟是熔断时间内还是再次被熔断了,因此使用了一个flag来做标记实现了功能。
本方法利用了断路器的状态统计熔断次数,代码修改自chatgpt
代码如下:
/**
* @ClassName: SentinelBlockHandler
* @Description: sentinel统一异常处理
* @author: liuzijian @ haiyisoft
* @Date: 2023/11/7 11:54
* @version: 1.0
**/
@Component
@Slf4j
public class SentinelBlockHandler implements BlockExceptionHandler {
private boolean flag = false;
@Resource
private ServerDegradeLogsRepository serverDegradeLogsRepository;
@Value("${server.port}")
private Integer serverPort;
private SentinelBlockHandler() {
// 私有构造方法,防止外部实例化
}
public static SentinelBlockHandler getInstance() {
return SingletonHolder.INSTANCE;
}
private static class SingletonHolder {
private static final SentinelBlockHandler INSTANCE = new SentinelBlockHandler();
}
static {
registerStateChangeObserver();
}
private static void registerStateChangeObserver() {
EventObserverRegistry.getInstance().addStateChangeObserver("logging",
(prevState, newState, rule, snapshotValue) -> {
List<CircuitBreakerStateChangeObserver> observers = EventObserverRegistry.getInstance().getStateChangeObservers();
if (newState == CircuitBreaker.State.OPEN) {
getInstance().flag = true;
System.err.println(String.format("===> resource: %s, %s -> OPEN at %d, snapshotValue=%.2f",
rule.getResource(), prevState.name(), TimeUtil.currentTimeMillis(), snapshotValue));
} else {
System.err.println(String.format("===> resource: %s, %s -> %s at %d",
rule.getResource(), prevState.name(), newState.name(), TimeUtil.currentTimeMillis()));
}
});
}
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws Exception {
/**
* 请求被限流了
*/
if (e instanceof FlowException){
httpServletResponse.setStatus(429);
ResponseService.httpResponse(httpServletResponse, ResponseStatus.SENTINEL_FLOW_ERROR);
log.error("请求被限流了:{}",e.getMessage());
}
/**
* 请求被熔断降级了
*/
else if (e instanceof DegradeException) {
System.out.println("进入熔断异常");
if (getInstance().flag){
InetAddress addr = InetAddress.getLocalHost();
String degradeText = "请求被熔断降级了:{" + e.getMessage() + "}";
ServerDegradeLogs serverDegradeLogs = new ServerDegradeLogs(addr.getHostAddress(), this.serverPort, degradeText);
serverDegradeLogsRepository.save(serverDegradeLogs);
getInstance().flag = false;
}
httpServletResponse.setStatus(429);
ResponseService.httpResponse(httpServletResponse, ResponseStatus.SENTINEL_DEGRADE_ERROR);
log.error("请求被熔断降级了:{}",e.getMessage());
}
/**
* 热点被限流了
*/
else if (e instanceof ParamFlowException) {
httpServletResponse.setStatus(429);
ResponseService.httpResponse(httpServletResponse, ResponseStatus.SENTINEL_PARAM_FLOW_ERROR);
log.error("热点被限流了:{}",e.getMessage());
}
/**
* 请求没有权限
*/
else if (e instanceof AuthorityException) {
httpServletResponse.setStatus(401);
ResponseService.httpResponse(httpServletResponse, ResponseStatus.UNAUTHORIZED);
log.error("请求没有权限:{}",e.getMessage());
}
}
}
参考链接:
断路器的使用:https://github.com/alibaba/Sentinel/issues/1939
文章来源:https://blog.csdn.net/weixin_44562957/article/details/134913006
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!