微服务组件 Sentinel(三)

一、整合 OpenFeign 进行降级

微服务组件 Sentinel(三)

1.1、引入依赖

<dependencies>
    <!-- Nacos 服务注册与发现 -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>

    <!--1.添加 openfeign 依赖-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>

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

</dependencies>

服务提供方的接口为

@RestController
@RequestMapping("/stock")
public class StockController {

    @RequestMapping("/reduce2")
    public String reduce2() {
        int a = 1 / 0;
        System.out.println("扣减库存!");
        return "扣减库存:" + port;
    }
}

1.2、加上 openfeign 接口的实现类

@Component
public class StockFeignServiceFallback implements StockFeignService{
    @Override
    public String reduce2() {
        return "降级了";
    }
}

1.3、application.yml,启动 feign 对 sentinel 的整合

feign:
  sentinel:
    # openfeign 整合 sentinel
    enabled: true

1.4、在 openfeign 接口上配置 fallback 的实现类

@FeignClient(value = "stock-server",path = "stock",contextId = "orderFeignSentinel",fallback = StockFeignServiceFallback.class)
public interface StockFeignService {
  // 声明需要调用的 rest 接口对应的方法
  @RequestMapping("/reduce2")
  String reduce2();
}

启动服务,看到此时服务提供方和调用方都已注册到 nacos 了。

微服务组件 Sentinel(三)

请求接口http://localhost:8041/order/add,发现针对远程服务进行了降级

微服务组件 Sentinel(三)

二、热点参数限流(热点识别流控)

热点即经常访问的数据,很多时候我们希望统计某个热点数据中访问频次最高的数据,并对其访问进行限制。常用的场景如热点商品的访问/操作控制,用户/IP 防刷等。实现原理为热点淘汰策略(LRU)+ Token Bucket 流控。

热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制, 仅对包含热点参数的资源调用生效。

准备接口

/**
 * 热点规则,必须使用 @SentinelResource,是对参数 id 进行流控的
 */
@RequestMapping("/get/{id}")
@SentinelResource(value = "getById",blockHandler = "HotBlockHandler")
public String getById(@PathVariable("id")Integer id) {
    System.out.println("正常访问");
    return "正常访问";
}

public String HotBlockHandler(@PathVariable("id")Integer id,BlockException e) {
    return "热点异常处理";
}

单机阈值:
1.假设参数大部分值都是热点参数,那么单机阈值主要针对热点参数进行流控,后续额外对普通的参数值进行流控。
2.假设大部值都是普通流量,则与上面相反。

配置热点参数规则
注意:资源名必须是@SentinelResource(value="资源名")中配置的资源名,热点规则依赖于注解

假设这个参数,大部分情况下都是普通流量,只有少部分值是热点流量
先针对普通流量,QPS 设置为 10,然后进行编辑
微服务组件 Sentinel(三)

然后对额外的热点流量进行流控设置,设置 QPS 为 2

微服务组件 Sentinel(三)

发现,访问 id 为 2时,只有超过 QPS 10 时,才会触发流控,但是访问 id 为 1 时,访问 QPS 超过 2就出现流控了

微服务组件 Sentinel(三)

微服务组件 Sentinel(三)

三、系统规则

在实际的生产环境中,可能会有如下问题
容量评估不到位,某个大流量接口限流配置不合理或没有配置,导致系统崩溃,来不及进行处理。
突然发现机器的Load和CPU usage等开始飚高,但却没有办法很快的确认到是什么原因造成的,也来不及处理。
当其中一-台机器挂了之后,本该由这台机器处理的流量被负载均衡到另外的机器上,另外的机器也被打挂了,引起系统雪崩。

这时,我们希望有个全局的兜底防护,即使缺乏容量评估也希望有一定的保护机制。即结合系统指标和服务容量,自适应动态调整流量
Sentinel 系统自适应限流从整体维度对应用入口流量进行控制,结合应用的Load、CPU 使用率、总体平均RT、入口 QPS 和并发线程数等几个维度的监控指标,通过自适应的流控策略,让系统的入口流量和系统的负载达到一个平衡, 让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。

什么是 load

  • Load自适应(仅对LinuxUnix-like机器生效):系统的 load1 作为启发指标,进行自适应系统保护。当系统 load1 超过设定的启发值,且系统当前的并发线程数超过估算的系统容量时才会触发系统保护(BBR阶段)。系统容量由系统的maxQps * minRt 估算得出。设定参考值一般是CPU cores * 2.5.
  • CPU usage (1.5.0+ 版本) : 当系统CPU使用率超过阈值即触发系统保护(取值范围0.0-1.0) ,比较灵敏。
  • 平均RT:当单台机器上所有入口流量的平均RT达到阈值即触发系统保护,单位是毫秒。
  • 并发线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。
  • 入口QPS:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。

可以看到系统负载基本在 15% 以上,设置系统保护为 cpu 阈值 20%

微服务组件 Sentinel(三)

微服务组件 Sentinel(三)

访问接口可以看到

微服务组件 Sentinel(三)

四、规则持久化

可以看到之前的无论是流控、降级、热点规则等,只要服务重启,就会丢失

sentinel 规则的推送有三种模式

推动模式 说明 优点 缺点
原始模式 API 将规则推送至客户端并直接更新到内存中,拓展写数据源(WritableDataSource) 简单,无任何依赖 不保证一致性:规则保存在内存中,重启即消失,严重不建议用于生产环境
Pull模式 拓展写数据源(WritableDataSource),客户端主动向某个规则管理中心定期轮询拉取规则,这个规则中心可以是 RDBMS,文件等 简单,无任何依赖,规则持久化 不保证一致性;实时性不保证,拉取过于频繁可能有性能问题
Push模式 拓展读数据源(ReadableDataSource),规则中心统一推送,客户端通过注册监听的方式时刻监听变化,比如使用 Nacos、Zookeeper等配置中心。这种方式有更好的实时性和一致性保证。生产环境一般采用 push 模式的数据源 规则持久化;一致性;快速 引入第三方依赖

4.1 原始模式

如果不做任何修改,Dashboard 的推送虽则方式是通过 API 将规则推送至客户端并直接更新到内存中

微服务组件 Sentinel(三)

这种做法的好处是简单,无依赖;坏处是应用重启,规则就会消失,仅用于简单测试,不能用于生产环境。

4.2、拉模式

pull模式的数据源(如本地文件、RDBMS 等)一般是可写入的。 使用时需要在客户端注册数据源:将对应的读数据源注册至对应的 RuleManager,将写数据源注册至transport的 WritableDataSourceRegistry 中。

4.3、推模式

生产环境下一般更常用的是 push模式的数据源。对于push模式的数据源,如远程配置中心(ZooKeeper, Nacos, Apollo等等), 推送的操作不应由 Sentinel 客户端进行,而应该经控制台统一进行管理,直接进行推送,数据源仅负责获取配置中心推送的配置并更新到本地。因此推送规则正确做法应该是配置中心控制台/Sentinel控制台→配置中心→Sentinel数据源→Sentinel,而不是经 Sentinel 数据源推送至配置中心。这样的流程就非常清晰了

官方 demo:sentinel-demo-nacos-datasource

引入依赖

<dependencies>
    <!--sentinel 启动器-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    </dependency>

    <dependency>
        <groupId>com.alibaba.csp</groupId>
        <artifactId>sentinel-datasource-nacos</artifactId>
    </dependency>
</dependencies>

nacos 中创建如下配置

nacos 配置中心配置流控规则

微服务组件 Sentinel(三)

系统规则

微服务组件 Sentinel(三)

[
  {
    "resource": "order/flow",
    "controlBehavior": 0,
    "count": 2,
    "grade": 1,
    "limitApp": "default",
    "strategy": 0
  }
]
[
    {
        "avgRt": 10,
        "highestSystemLoad": 5.0,
        "maxTrhead": 10,
        "qps": 20.0
    }
]

application.yml 配置文件内容如下

server:
  port: 8070
spring:
  application:
    name: order-sentinel
  cloud:
    sentinel:
      transport:
        dashboard: 192.168.33.62:8858
        clientIp: 192.168.33.27
      # 默认将调用链路收敛
      web-context-unify: false
      datasource:
        # 可以自定义
        flow-rule:
          nacos:
            server-addr: 192.168.33.62:8847
            username: kunjuee
            password: we753951.
            data-id: order-sentinel-flow-rule
            rule-type: flow
        system:
          nacos:
            server-addr: 192.168.33.62:8847
            username: kunjuee
            password: we753951.
            data-id: order-sentinel-system-rule
            rule-type: system

流控规则

微服务组件 Sentinel(三)

系统规则

微服务组件 Sentinel(三)

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!