Sentinel服务保护

发布于:2025-02-10 ⋅ 阅读:(60) ⋅ 点赞:(0)

Sentinel服务保护

1. 简介

Sentinel是阿里巴巴开源的一款服务保护框架,目前已经加入SpringCloudAlibaba中。

Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件,主要以流量为切入点,从流量控制、流量路由、熔断降级、系统自适应保护等多个维度来帮助用户保障微服务的稳定性。

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

Sentinel 的使用可以分为两个部分:

  • 核心库(Jar包):不依赖任何框架/库,能够运行于 Java 8 及以上的版本的运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持。在项目中引入依赖即可实现服务限流、隔离、熔断等功能。
  • 控制台(Dashboard):Dashboard 主要负责管理推送规则、监控、管理机器信息等。

2. 安装

2.1 下载jar包

下载地址:https://github.com/alibaba/Sentinel

2.2 运行

将jar包放在任意非中文、不包含特殊字符的目录下:

java -Dserver.port=8090 -Dcsp.sentinel.dashboard.server=localhost:8090 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar

2.3 访问

http://localhost:8090/#/dashboard/home

3. 微服务整合

3.1 引入依赖

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

3.2 配置控制台

spring:
  cloud: 
    sentinel:
      transport:
        dashboard: localhost:8090

3.3 访问微服务接口

重启微服务,调用服务接口,查看sentinel-dashboard

3.4 簇点链路配置

默认情况下Sentinel会把路径作为簇点资源的名称,无法区分路径相同但请求方式不同的接口,查询、删除、修改等都被识别为一个簇点资源。

修改Sentinel的请求方式前缀,把请求方式 + 请求路径作为簇点资源名:

微服务application.yml中添加配置:

spring:
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8090
      http-method-specify: true # 开启请求方式前缀

重启服务。

4. 请求限流

4.1 配置

在簇点链路后面点击流控按钮,即可对其做限流配置:

在这里插入图片描述

在这里插入图片描述

4.2 JMeter测试

使用JMeter测试限流

在这里插入图片描述

Sentinel实时监控:

在这里插入图片描述

5. 线程隔离

限流可以降低服务器压力,尽量减少因并发流量引起的服务故障的概率,但并不能完全避免服务故障。一旦某个服务出现故障,我们必须隔离对这个服务的调用,避免发生雪崩。

比如,查询购物车的时候需要查询商品,为了避免因商品服务出现故障导致购物车服务级联失败,我们可以把购物车业务中查询商品的部分隔离起来,限制可用的线程资源:

在这里插入图片描述

这样,即便商品服务出现故障,最多导致查询购物车业务故障,并且可用的线程资源也被限定在一定范围,不会导致整个购物车服务崩溃。

5.1 OpenFeign整合Sentinel

application.yml文件,开启Feign的sentinel功能:

feign:
  sentinel:
    enabled: true # 开启feign对sentinel的支持

配置application.yml文件,修改tomcat连接:

server:
  port: 8082
  tomcat:
    threads:
      max: 50 # 允许的最大线程数
    accept-count: 50 # 最大排队等待数量
    max-connections: 100 # 允许的最大连接

然后重启cart-service服务。

5.2 配置线程隔离

点击查询商品的FeignClient对应的簇点资源后面的流控按钮:

在这里插入图片描述

注意,这里勾选的是并发线程数限制,也就是说这个查询功能最多使用5个线程,而不是5QPS。如果查询商品的接口每秒处理2个请求,则5个线程的实际QPS在10左右,而超出的请求自然会被拒绝。

6. 服务熔断

6.1 熔断概念

服务熔断是指当调用方访问服务时,通过断路器做代理进行访问。断路器会持续观察服务返回的成功、失败状态,当失败超过设置的阈值时,断路器会打开,请求就不能真正地访问到服务了,从而避免服务故障的进一步蔓延,保障系统的整体稳定性。

6.2 Sentinel实现服务熔断

Sentinel通过定义资源和规则来实现熔断降级功能,当资源的错误率或响应时间超过预设的阈值时,Sentinel会触发熔断机制,拒绝后续的请求,直到资源恢复正常。

6.3 Sentinel服务熔断机制

Sentinel服务熔断的工作机制:

  • 监控阶段‌:Sentinel使用统计窗口来收集关于资源的运行数据,包括请求量、错误率、响应时间等。
  • 判断阶段‌:根据预设的熔断规则(如错误率阈值、响应时间阈值等),Sentinel判断是否需要触发熔断机制。
  • 熔断阶段‌:当满足熔断条件时,Sentinel会打开断路器,拒绝后续的请求,并返回相应的错误信息。
  • 恢复阶段‌:经过一段预设的时间(称为熔断时间窗),Sentinel会进入半开状态,允许少量请求通过以检测资源是否已经恢复正常。如果请求成功且没有错误,则完全恢复对该资源的访问;否则,继续延长熔断时间或重新进入熔断状态。

6.4 编写降级逻辑

触发限流或熔断后的请求不一定要直接报错,也可以返回一些默认数据或者友好提示,用户体验会更好。

给FeignClient编写失败后的降级逻辑有两种方式:

  • 方式一:FallbackClass,无法对远程调用的异常做处理
  • 方式二:FallbackFactory,可以对远程调用的异常做处理,我们一般选择这种方式。

FallBackFactory方式实现

步骤一:在hm-api模块中给ItemClient定义降级处理类,实现FallbackFactory

package com.hmall.api.client.fallback;

import com.hmall.api.client.ItemClient;
import com.hmall.api.dto.ItemDTO;
import com.hmall.api.dto.OrderDetailDTO;
import com.hmall.common.exception.BizIllegalException;
import com.hmall.common.utils.CollUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.FallbackFactory;

import java.util.Collection;
import java.util.List;

@Slf4j
public class ItemClientFallback implements FallbackFactory<ItemClient> {
    @Override
    public ItemClient create(Throwable cause) {
        return new ItemClient() {
            @Override
            public List<ItemDTO> queryItemByIds(Collection<Long> ids) {
                log.error("远程调用ItemClient#queryItemByIds方法出现异常,参数:{}", ids, cause);
                // 查询购物车允许失败,查询失败,返回空集合
                return CollUtils.emptyList();
            }

            @Override
            public void deductStock(List<OrderDetailDTO> items) {
                // 库存扣减业务需要触发事务回滚,查询失败,抛出异常
                throw new BizIllegalException(cause);
            }
        };
    }
}

步骤二:在hm-api模块中的com.hmall.api.config.DefaultFeignConfig类中将ItemClientFallback注册为一个Bean

public class DefaultFeignConfig {
    @Bean
    public Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }
    @Bean
    public RequestInterceptor userInfoRequestInterceptor(){
        return new RequestInterceptor() {
            @Override
            public void apply(RequestTemplate template) {
                // 获取登录用户
                Long userId = UserContext.getUser();
                if(userId == null) {
                    // 如果为空则直接跳过
                    return;
                }
                // 如果不为空则放入请求头中,传递给下游微服务
                template.header("User-Token", userId.toString());
            }
        };
    }
    @Bean
    public ItemClientFallback itemClientFallback() {
        return new ItemClientFallback();
    }
}

步骤三:在hm-api模块中的ItemClient接口中使用ItemClientFallbackFactory

@FeignClient(value = "item-service",configuration = DefaultFeignConfig.class,fallbackFactory = ItemClientFallback.class)
public interface ItemClient {
    @GetMapping("/items")
    List<ItemDTO> queryItemByIds(@RequestParam("ids") Collection<Long> ids);
    @PutMapping("/items/stock/deduct")
    void deductStock(@RequestBody List<OrderDetailDTO> items);
}

重启服务。

6.5 服务熔断配置

Sentinel中的断路器不仅可以统计某个接口的慢请求比例,还可以统计异常请求比例。当这些比例超出阈值时,就会熔断该接口,即拦截访问该接口的一切请求,降级处理;当该接口恢复正常时,再放行对于该接口的请求。

断路器的工作状态切换有一个状态机来控制:

在这里插入图片描述

状态机包括三个状态:

  • closed:关闭状态,断路器放行所有请求,并开始统计异常比例、慢请求比例。超过阈值则切换到open状态
  • open:打开状态,服务调用被熔断,访问被熔断服务的请求会被拒绝,快速失败,直接走降级逻辑。Open状态持续一段时间后会进入half-open状态
  • half-open:半开状态,放行一次请求,根据执行结果来判断接下来的操作。
    • 请求成功:则切换到closed状态
    • 请求失败:则切换到open状态

在sentinel-dashboard配置阈值:

态:

  • closed:关闭状态,断路器放行所有请求,并开始统计异常比例、慢请求比例。超过阈值则切换到open状态
  • open:打开状态,服务调用被熔断,访问被熔断服务的请求会被拒绝,快速失败,直接走降级逻辑。Open状态持续一段时间后会进入half-open状态
  • half-open:半开状态,放行一次请求,根据执行结果来判断接下来的操作。
    • 请求成功:则切换到closed状态
    • 请求失败:则切换到open状态

在sentinel-dashboard配置阈值:

在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到