Spring Cloud:Sentinel异常处理(六)

Sentinel:用来做服务保护的框架,包括限流,熔断降级等。

官网:https://sentinelguard.io/zh-cn/index.html


1.基础场景

        下载Sentinel的控制台后,不要解压,在当前文件夹打开cmd:

        控制台输入:java -jar sentinel-dashboard-1.8.6.jar即可成功运行,访问本地端口8080,账号密码均为Sentinel

        回到项目导入依赖:

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>

        导入控制台:

#application-feign.yml
spring:
  cloud:
    openfeign:
      client:
        config:
          default: # 默认配置
            logger-level: full # 日志级别
            connect-timeout: 1000 # 连接超时
            read-timeout: 2000 #读取超时
          service-product: # service-product服务配置
            logger-level: full
            connect-timeout: 3000
            read-timeout: 5000
    sentinel:
      transport:
        dashboard: localhost:8080 # sentinel控制台地址
      eager: true #项目一打开自动启动控制台
feign:
  sentinel:
    enabled: true

        接着为资源创建保护机制:

//OrderServiceImpl.java

    @SentinelResource(value = "createOrder")//创建保护机制
    @Override
    public Order createOrder(Long productId, Long userId) {
        //使用Feign完成远程调用
        Product product = productFeignClient.getProductById(productId);
        Order order = new Order();
        order.setId(1L);
        order.setTotalAmount(product.getPrice().multiply(new BigDecimal(product.getNum())));
        order.setUserId(userId);
        order.setNickName("蔡徐坤");
        order.setAddress("坤坤村");
        order.setProductsList(Arrays.asList(product));
        return order;
    }

        启动Naocs,启动Sentinel,启动项目:

        

        里面的具体调试和Naocs很相像,自己尝试即可。

2.异常处理

        这里我们想让前端报错返回JSON数据,而不是默认页面。而有以下四种方法来实现我们的愿望

2.1.Web接口

        先创建一个异常处理类:        

        在异常处理类中自定义我们的异常处理方法:

@Component
public class MyBlockExceptionHandler implements BlockExceptionHandler {
    private ObjectMapper objectMapper = new ObjectMapper();
    @Override
    public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, String s, BlockException e) throws Exception {
        httpServletResponse.setCharacterEncoding("utf-8");
        PrintWriter writer = httpServletResponse.getWriter();


        R error = R.error(500, s + "限流了,原因:"+ e.getClass());
        String json = objectMapper.writeValueAsString(error);
        writer.write(json);
        writer.flush();
        writer.close();
    }
}

        这里自定义了一个R对象,放在我们的model.common模块下:

@Data
public class R {
    //是将来返回前端的JSON数据的对象
    private Integer code;
    private String message;
    private Object data;

    public static R ok() {
        R r = new R();
        r.setCode(200);
        return r;
    }
    public static R ok(String message,Object data) {
        R r = new R();
        r.setCode(200);
        r.setMessage(message);
        r.setData(data);
        return r;
    }
    public static R error() {
        R r = new R();
        r.setCode(500);
        return r;
    }

    public static R error(Integer code, String message) {
        R r = new R();
        r.setCode(code);
        r.setMessage(message);
        return r;
    }
}

        这样的话再次异常处理的时候就是返回我们自定义的异常了:

2.2.@SentinelResource

        兜底回调机制:被本注解标注的资源,当访问时没有违反规则,则调用真实的业务逻辑数据;但是如果违反了规则,则调用兜底逻辑数据。

        在ServiceImpl中:

//这里标注了@SentinelResource
//blockHandler = "CreateOrderFallBack" 兜底回调
@SentinelResource(value = "createOrder",blockHandler = "CreateOrderFallBack")
    @Override
    public Order createOrder(Long productId, Long userId) {
        //使用Feign完成远程调用
        Product product = productFeignClient.getProductById(productId);
        Order order = new Order();
        order.setId(1L);
        order.setTotalAmount(product.getPrice().multiply(new BigDecimal(product.getNum())));
        order.setUserId(userId);
        order.setNickName("蔡徐坤");
        order.setAddress("坤坤村");
        order.setProductsList(Arrays.asList(product));
        return order;
    }
//兜底回调
    public Order CreateOrderFallBack(Long productId, Long userId,Throwable throwable){
        Order order = new Order();
        order.setId(0L);
        order.setTotalAmount(new BigDecimal(0));
        order.setUserId(userId);
        order.setNickName("未知用户");
        order.setAddress("信息异常" + throwable.getClass());

        return order;
    }

        这样的话,合法的数据和不合法的数据也就分开了,不会报一个白错误让你晕头脑。

2.3.Openfeign        

        远程调用,这个之前就用过。详情请见上节。

        最后就是Sphu硬编码方法,理解即可。详情见

【尚硅谷2025最新SpringCloud教程,springcloud从入门到大牛】 https://www.bilibili.com/video/BV1UJc2ezEFU/?p=35&share_source=copy_web&vd_source=3c83936ad44c69171f2fe73f94be606b

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值