12. SpringCloudAlibaba 实践笔记:Sentinel 项目集成

安装 Sentinel 控制台

https://github.com/alibaba/Sentinel/releases 下载控制台,下载后解压,并运行启动命令

java -D"server.port=8888" -D"csp.sentinel.dashboard.server=localhost:8888" -D"project.name=sentinel-dashboard" -jar sentinel-dashboard-1.8.8.jar

启动后在浏览器中输入 http://localhost:8888 访问 Sentinel 控制台,如下所示
image

输入默认的用户名 sentinel 和密码 sentinel,登录 Sentinel 控制台,如下所示。

image
Sentinel 控制台下载并启动成功。

项目集成

订单微服务集成

添加依赖

在订单微服务添加 sentinel 的依赖

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

修改应用配置

在订单微服务的shop-order的application.yml文中加入Sentinel相关的配置

spring:
  cloud:
    sentinel:
      transport:
        port: 9999   #指定和Sentinel控制台交互的端口,任意指定一个未使用的端口即可
        dashboard: 127.0.0.1:8888  #Sentinel控制台服务地址

新增测试接口

订单微服务的 OrderController 类中新增一个测试接口

@GetMapping(value = "/test_sentinel")
public String testSentinel(){
    log.info("测试Sentinel");
    return "sentinel";
}

启动订单服务

启动订单微服务,在浏览器中输入 http://localhost:8080/order/test_sentinel 访问在订单微服务中新增的接口。

查看 Sentinel 页面

刷新 Sentinel 页面,会发现已经显示了订单微服务的菜单
image

注意:直接启动订单微服务和 Sentinel,会发现 Sentinel 中没有订单微服务的数据,因为 Sentinel 是懒加载机制,所以需要访问一下接口,再去访问 Sentinel 就有数据了。

集成 Sentinel 限流功能

新增流量规则

找到簇点链路

在 Sentinel 控制台找到 server-order 下的簇点链路菜单,如下所示。
image

新增流控规则

image
点击流控按钮会显示 新增流控规则 的弹出框,在单机阈值后直接填写1,表示 test_sentinel 接口的QPS为1,每秒访问1次。
image

不断刷新 test_sentinel 接口

在浏览器上不断刷新test_sentinel接口,当每秒访问的次数超过1次时,会被Sentinel限流
image

对提交订单的接口限流

访问提交订单接口

首先访问下提交订单的接口 http://localhost:8080/order/submit_order使得Sentinel中能够捕获到提交订单的接口,并点击操作中的流控按钮。
image
24.cnblogs.com/blog/2630273/202411/2630273-20241106232216517-1904026905.png)

为提交订单接口新增流控规则

image

不断刷新提交订单的接口

不断刷新 http://localhost:8080/order/submit_order 使得每秒访问的频率超过1次,会被Sentinel限流
image

Feign 整合 Sentinel 实现容错

使用 Sentinel 实现订单微服务的上游服务的容错。
首先按照上面添加依赖步骤,向 shop-order 服务添加 sentinel 依赖,修改 application.yaml 文件,并且启动 sentinel。

为调用上游服务配置容错

在使用 Feign 进行远程调用时,为了对上游服务配置容错机制,需要对上游服务定义 FallBack 类

为用户微服务实现容错

创建UserServiceFallBack类实现UserService接口,用于调用用户微服务的容错类。

@Component
public class UserServiceFallBack implements UserService {
    // 当出现错误时,返回默认的 User 对象。
    @Override
    public User getUser(Long uid) {
        User user = new User();
        user.setId(-1L);
        return user;
    }
}

注意:容错类需要实现一个被容错的接口,并实现这个接口的方法。

在订单微服务的 UserService 接口上的 @FeignClient 注解上指定容错类。

@FeignClient(value = "server-user", fallback = UserServiceFallBack.class) // 指定 fallback
public interface UserService {

    @GetMapping(value = "/user/get/{uid}")
    User getUser(@PathVariable("uid") Long uid);
}

为商品微服务实现容错

创建 ProductServiceFallBack 类实现 ProductService 接口,用于调用商品微服务的容错类。

@Component
public class ProductServiceFallBack implements ProductService {
    @Override
    public Product getProduct(Long pid) {
        Product product = new Product();
        product.setId(-1L);
        return product;
    }

    @Override
    public Result<Integer> updateCount(Long pid, Integer count) {
        Result<Integer> result = new Result<>();
        result.setCode(1001);
        result.setCodeMsg("触发了容错逻辑");
        return result;
    }
}

在订单微服务的 ProductService 接口上的 @FeignClient 注解上指定容错类

@FeignClient(value = "server-product", fallback = ProductServiceFallBack.class) // 指定 fallback
public interface ProductService {

    /**
     * 获取商品信息
     */
    @GetMapping(value = "/product/get/{pid}")
    Product getProduct(@PathVariable("pid") Long pid);

    /**
     * 更新库存数量
     */
    @GetMapping(value = "/product/update_count/{pid}/{count}")
    Result<Integer> updateCount(@PathVariable("pid") Long pid, @PathVariable("count") Integer count);
}

为订单微服务添加容错逻辑

在 OrderServiceImpl 的 saveOrder() 方法中,增加容错逻辑。

User user = userService.getUser(orderParams.getUserId());
if (user == null){
    throw new RuntimeException("未获取到用户信息: " + JSONObject.toJSONString(orderParams));
}

if (user.getId() == -1) { // 返回 userid = -1,说明触发了容错逻辑。
    throw new RuntimeException("触发了用户微服务的容错逻辑: " + JSONObject.toJSONString(orderParams));
}
Product product = productService.getProduct(orderParams.getProductId());
if (product == null){
    throw new RuntimeException("未获取到商品信息: " + JSONObject.toJSONString(orderParams));
}
if (product.getId() == -1) { // 返回 productid = -1,说明触发了容错逻辑。
    throw new RuntimeException("触发了商品微服务的容错逻辑: " + JSONObject.toJSONString(orderParams));
}
//#####################省略N行代码##########################
Result<Integer> result = productService.updateCount(orderParams.getProductId(), orderParams.getCount());
if (result.getCode() == 1001){ // 返回 状态码 = 1001,说明触发了容错逻辑。
    throw new RuntimeException("触发了商品微服务的容错逻辑: " + JSONObject.toJSONString(orderParams));
}
if (result.getCode() != HttpCode.SUCCESS){
    throw new RuntimeException("库存扣减失败");
}
posted @ 2024-11-06 23:23  Jacob-Chen  阅读(482)  评论(0)    收藏  举报