java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > SpringCloud中Sentinel基础场景和异常处理

SpringCloud中Sentinel基础场景和异常处理方式

作者:Xwzzz_

这篇文章主要介绍了SpringCloud中Sentinel基础场景和异常处理方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

Sentinel 是一个由 阿里巴巴 开源的分布式系统流量控制组件,专注于为微服务架构提供流量控制、熔断降级、系统负载保护等功能。

它特别适用于高并发、高可用性的分布式系统,能够帮助开发者保护系统免于因流量过载、系统崩溃、依赖不可用等情况而导致的服务不可用。

一、Sentinel 的核心功能

流量控制(Traffic Control)

熔断降级(Circuit Breaker)

系统负载保护(System Load Protection)

热点参数限流(Hot Spot Parameter Flow Control)

监控与报警

集群模式

二、使用 Sentinel

添加依赖:

在 Spring Boot 项目中集成 Sentinel,首先需要在 pom.xml 中添加相关的依赖:

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-core</artifactId>
    <version>1.8.3</version>
</dependency>

使用 @SentinelResource 注解:

在方法上使用 @SentinelResource 注解来定义流量控制和熔断降级逻辑:

@SentinelResource(value = "createOrder")
@Override
public Order createOrder(Long productId, Long userId) {
    Product product = getProductFromRemoteWithLoadBalanceAnnotation(productId);

    // 使用 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("zhangsan");
    
    return order;
}

@SentinelResource(value = "createOrder"):为 createOrder 方法添加了 Sentinel 的流量控制和熔断降级功能。这意味着该方法在执行时会受 Sentinel 管控,触发流量控制或熔断时,会执行相应的降级逻辑(如返回默认值或调用备用方法)。

productFeignClient.getProductById(productId):使用 Feign 远程调用其他服务获取产品信息。productFeignClient 是通过 Feign 客户端定义的接口,能够调用远程服务 getProductById 方法来获取指定 productId 的产品信息。

三、异常处理

其中异常处理流程主要分为三个大类:Web 接口的异常处理,@SentinelResource和 OpenFeign 调用的异常处理。涉及了不同的组件和处理方法:

1. Web 接口中的异常处理

在 Web 接口的异常处理中,主要使用 SentinelWebInterceptor 来拦截和处理请求中的异常。

1.1 SentinelWebInterceptor

1.2 默认 BlockExceptionHandler

1.3 自定义 BlockExceptionHandler

import com.fasterxml.jackson.databind.ObjectMapper;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;

@Component
public class MyBlockExceptionHandler implements BlockExceptionHandler {

    private ObjectMapper objectMapper = new ObjectMapper();  // 用于将错误信息转换成 JSON 格式

    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response,
                       String resourceName, BlockException e) throws Exception {
        // 获取响应的 PrintWriter 用于向客户端输出响应内容
        PrintWriter writer = response.getWriter();

        // 设置响应的内容类型为 JSON
        response.setContentType("application/json;charset=utf-8");

        // 创建一个自定义的错误信息对象 R,包含错误的代码和消息
        R error = R.error(500, resourceName + " 被Sentinel 限制了, 原因: " + e.getMessage());

        // 使用 ObjectMapper 将错误对象转换为 JSON 字符串
        String json = objectMapper.writeValueAsString(error);

        // 将 JSON 写入响应输出流
        writer.write(json);
    }
}

@Component 注解

ObjectMapper 实例化

handle 方法

2. @SentinelResource 注解中的异常(常用于控制器以外的类上)

在使用 @SentinelResource 注解时,我们可以为特定资源配置 流量控制降级熔断 等处理。

它可以和 blockHandlerfallback 配合使用,确保服务在流量限制或异常发生时进行降级处理。

2.1 SentinelResourceAspect

2.2 blockHandler

@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("zhangsan");
    order.setAddress("西安工业大学");

    // 远程查询商品列表
    order.setProductList(Arrays.asList(product));

    return order;
}

// 降级回调
public Order createOrderFallback(Long productId, Long userId, BlockException e) {
    Order order = new Order();
    order.setId(0L);
    order.setTotalAmount(new BigDecimal("0"));
    order.setUserId(userId);
    order.setNickName("未注册用户");
    order.setAddress("异常信息: " + e.getClass());

    return order;
}

这段代码保证了在请求被限流或发生异常时,能够回退到一个默认的响应,从而避免系统崩溃。具体通过 @SentinelResource 注解、blockHandler 机制实现了流量控制与异常降级处理。在控制后返回一个兜底回调数据。

2.3 fallback

最终总结起来,我们的最佳实战用法就是SentinelResource一般标注在非control的这些层,你想要给哪些方法进行保护,你就加上这个注解,一旦违反规则以后,如果业务规定有兜底回调的数据,那么就使用block handler去来指定兜底回调,如果业务没规定有兜底回调,那我们也可以不用任何一种回调机制,直接让异常抛给全局,由项目的spring boot全局异常处理器进行处理。

3. OpenFeign 调用中的异常处理

OpenFeign 的调用中,Sentinel 同样提供了流量控制和熔断降级的功能。

3.1 SentinelFeign.builder()

3.2 fallback

Feign 客户端接口

@FeignClient(value = "service-product", fallback = ProductFeignClientFallback.class) // feign客户端
public interface ProductFeignClient {
    @GetMapping("/product/{id}")
    Product getProductById(@PathVariable("id") Long id);
}

@FeignClient:定义了一个 Feign 客户端接口,value = "service-product" 表示它会向 service-product 服务发起请求,fallback 指定了降级,ProductFeignClientFallback.class,当远程调用失败时会触发该降级方法。

Feign 客户端的降级处理:

@Component
public class ProductFeignClientFallback implements ProductFeignClient {
    @Override
    public Product getProductById(Long id) {
        System.out.println("降级回调....");
        Product product = new Product();
        product.setId(id);
        product.setPrice(new BigDecimal("0"));
        product.setProductName("未知商品");
        product.setNum(0);
        return product;
    }
}

4. Spring Boot 异常处理

4.1 SpringBoot 异常处理

四、fallback 和 blockHandler 的区别

1. fallback

2. blockHandler

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文