服务限流:Sentinel 在 Spring Cloud 中的应用

Spring Cloud 里的“守门大爷”:Sentinel 限流保平安

各位看官,大家好!今天咱就来聊聊 Spring Cloud 这个大家庭里一个非常重要的“成员”—— Sentinel,它就像咱们小区门口的“守门大爷”,负责把控流量,防止“坏人”(过高的流量)冲进来,破坏咱们系统的安全和稳定。

在微服务架构下,服务之间的调用关系错综复杂,一个请求可能要经过多个服务才能完成。如果某个服务扛不住压力,就会像多米诺骨牌一样,导致整个系统崩溃。这时候,Sentinel 就派上用场了。它能对服务进行限流、熔断、降级等操作,保证系统的可用性。

一、 什么是 Sentinel?它凭什么当“守门大爷”?

Sentinel,中文意思是“哨兵”,顾名思义,就是用来站岗放哨的。它是一个开源的、高可用的流量控制、熔断降级框架。

用官方的话来说,Sentinel 具有以下特点:

  • 丰富的应用场景: Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。
  • 完备的实时监控: Sentinel 提供实时的监控数据,方便我们了解系统的运行状况。
  • 广泛的生态: Sentinel 提供了对 Spring Cloud、Dubbo 等流行框架的良好支持。
  • SPI 可扩展性: Sentinel 提供了丰富的 SPI 接口,方便我们进行定制化开发。

简单来说,Sentinel 就是一个功能强大、性能优异、易于使用的流量控制框架。有了它,咱们就能轻松应对各种流量高峰,保证系统的稳定运行。

二、 Sentinel 能做些什么?“守门大爷”的十八般武艺

咱们的“守门大爷”Sentinel 可不是只会站岗,它可是身怀十八般武艺,样样精通。

  1. 流量控制(限流): 这是 Sentinel 最基本的功能。它可以限制某个接口或服务的请求速率,防止流量过大导致系统崩溃。

    • QPS 限流: 限制每秒钟的请求数量。比如限制某个接口每秒最多只能处理 100 个请求。
    • 线程数限流: 限制同时访问某个接口的线程数量。比如限制某个接口最多只能有 20 个线程同时访问。
    • 其他限流方式: Sentinel 还支持基于调用关系、基于来源等多种限流方式。
  2. 熔断降级: 当某个服务出现故障时,Sentinel 可以自动熔断该服务,防止故障蔓延到整个系统。

    • 平均响应时间熔断: 当某个接口的平均响应时间超过设定的阈值时,Sentinel 会熔断该接口。
    • 异常比例熔断: 当某个接口的异常比例超过设定的阈值时,Sentinel 会熔断该接口。
    • 异常数熔断: 当某个接口的异常数量超过设定的阈值时,Sentinel 会熔断该接口。
  3. 系统保护: Sentinel 可以对整个系统进行保护,防止系统负载过高导致崩溃。

    • load 自适应保护: Sentinel 会根据系统的 load 情况自动调整流量控制策略。
    • CPU 使用率保护: 当 CPU 使用率超过设定的阈值时,Sentinel 会拒绝部分请求。
    • 入口流量控制: Sentinel 可以限制进入系统的总流量。
  4. 热点参数限流: 针对访问频率特别高的参数进行限流。比如针对某个用户的 ID 进行限流,防止恶意用户刷接口。

  5. 链路流控: 根据调用链路的拓扑关系进行流量控制。比如可以限制某个服务对下游服务的调用频率。

三、 如何在 Spring Cloud 中使用 Sentinel?手把手教你配置

说了这么多,咱们来点实际的,看看如何在 Spring Cloud 中使用 Sentinel。

1. 引入依赖

首先,在你的 Spring Cloud 项目中引入 Sentinel 的依赖。

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

2. 配置 Sentinel

application.propertiesapplication.yml 文件中配置 Sentinel。

spring:
  application:
    name: your-service-name
  cloud:
    sentinel:
      enabled: true  # 开启 Sentinel
      transport:
        dashboard: localhost:8080  # Sentinel 控制台地址
        port: 8719 # sentinel客户端端口
      # 关闭热点参数自动降级
      degrade:
        enabled: false

3. 定义资源

我们需要告诉 Sentinel 哪些接口或方法需要保护。可以使用 @SentinelResource 注解来定义资源。

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @GetMapping("/hello")
    @SentinelResource("hello")
    public String hello() {
        return "Hello, Sentinel!";
    }

    @GetMapping("/test")
    @SentinelResource(value = "test", fallback = "testFallback", blockHandler = "testBlockHandler")
    public String test() {
        return "Test, Sentinel!";
    }

    public String testFallback(Throwable throwable) {
        return "Test Fallback: " + throwable.getMessage();
    }

    public String testBlockHandler(com.alibaba.csp.sentinel.slots.block.BlockException blockException) {
        return "Test Block Handler: " + blockException.getMessage();
    }
}
  • @SentinelResource("hello"):定义一个名为 "hello" 的资源,Sentinel 会对这个资源进行流量控制和熔断降级。
  • value:资源名称,必须唯一。
  • fallback:指定降级方法,当接口发生异常时,会调用该方法。注意:fallback 方法必须和原方法在同一个类中,且参数列表要兼容(可以多一个Throwable参数接收异常)。
  • blockHandler:指定限流或熔断时的处理方法,当接口被限流或熔断时,会调用该方法。注意:blockHandler 方法必须和原方法在同一个类中,且参数列表要兼容(可以多一个BlockException参数接收异常)。

4. 配置限流规则

启动 Sentinel 控制台,地址就是上面配置的 localhost:8080

在控制台上,可以配置各种限流规则。比如,我们可以配置 "hello" 接口的 QPS 限流规则,限制每秒钟最多只能处理 5 个请求。

配置流程:

  1. 访问Sentinel控制台,点击“簇点链路”或者“资源”,找到你需要配置的资源(比如 “hello”)。
  2. 点击 “流控”,添加流控规则。
  3. 配置流控规则:
    • 资源名:默认为你选择的资源,比如“hello”
    • 针对来源:默认为default,表示不区分来源。
    • 阈值类型:选择 QPS 或线程数。
    • 单机阈值:设置具体的阈值,比如 5(表示每秒最多允许 5 个请求)。
    • 流控模式:选择直接拒绝、Warm Up、排队等待。
    • 是否集群:根据需要选择是否开启集群流控。

5. 测试

启动你的 Spring Cloud 项目,然后访问 /hello 接口。如果访问频率超过了设定的阈值,Sentinel 就会拒绝部分请求。当你配置了blockHandler方法,就会执行该方法,返回自定义的提示信息。

四、 代码示例:更深入的讲解

光说不练假把式,咱们来几个更具体的代码示例,帮助大家更深入地理解 Sentinel 的使用。

示例 1:QPS 限流

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class RateLimitController {

    @GetMapping("/rateLimit")
    @SentinelResource(value = "rateLimit", blockHandler = "rateLimitBlockHandler")
    public String rateLimit() {
        return "Rate Limit Success!";
    }

    public String rateLimitBlockHandler(com.alibaba.csp.sentinel.slots.block.BlockException blockException) {
        return "Rate Limit Blocked!";
    }
}

在 Sentinel 控制台上,配置 "rateLimit" 接口的 QPS 限流规则,限制每秒钟最多只能处理 2 个请求。

示例 2:熔断降级

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DegradeController {

    @GetMapping("/degrade")
    @SentinelResource(value = "degrade", fallback = "degradeFallback")
    public String degrade() throws InterruptedException {
        // 模拟服务不稳定,偶尔会抛出异常
        if (Math.random() < 0.5) {
            throw new RuntimeException("Service Unavailable!");
        }
        Thread.sleep(100); // 模拟服务响应时间
        return "Degrade Success!";
    }

    public String degradeFallback(Throwable throwable) {
        return "Degrade Fallback: " + throwable.getMessage();
    }
}

在 Sentinel 控制台上,配置 "degrade" 接口的异常比例熔断规则,设置异常比例为 0.6。

示例 3:热点参数限流

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HotParamController {

    @GetMapping("/hotParam")
    @SentinelResource(value = "hotParam", blockHandler = "hotParamBlockHandler")
    public String hotParam(@RequestParam String id) {
        return "Hot Param: " + id;
    }

    public String hotParamBlockHandler(String id, com.alibaba.csp.sentinel.slots.block.BlockException blockException) {
        return "Hot Param Blocked: " + id;
    }
}

在 Sentinel 控制台上,配置 "hotParam" 接口的热点参数限流规则,针对参数 "id" 进行限流。

五、 Sentinel 的高级用法:更上一层楼

除了上面介绍的基本用法,Sentinel 还有很多高级用法,可以帮助我们更好地保护系统。

  1. 自定义规则: Sentinel 提供了 SPI 接口,我们可以自定义限流规则、熔断规则等。
  2. 集群流控: 在分布式环境下,可以使用 Sentinel 的集群流控功能,对整个集群的流量进行控制。
  3. 动态配置: 可以使用 Nacos、Consul 等配置中心,动态更新 Sentinel 的规则。
  4. 监控告警: 可以将 Sentinel 的监控数据接入 Prometheus、Grafana 等监控系统,实现实时监控和告警。

六、 Sentinel 的优缺点:客观评价

任何事物都有两面性,Sentinel 也不例外。

优点:

  • 功能强大,支持多种限流和熔断策略。
  • 性能优异,对系统性能影响较小。
  • 易于使用,配置简单。
  • 社区活跃,文档完善。

缺点:

  • 学习成本较高,需要一定的学习时间才能掌握。
  • 配置规则较为繁琐,需要手动配置。
  • 对 Spring Cloud 的版本有一定要求。

七、 Sentinel 与 Hystrix 的对比:谁更胜一筹?

在 Sentinel 出现之前,Hystrix 是 Spring Cloud 中常用的熔断降级框架。那么,Sentinel 和 Hystrix 相比,谁更胜一筹呢?

特性 Sentinel Hystrix
功能 限流、熔断、降级、系统保护、热点参数限流 熔断、降级
性能 较高 较低
易用性 较易 较易
社区活跃度 较高 较低(已停止维护)
监控 提供实时监控数据 需要集成第三方监控系统,且数据不如Sentinel丰富
生态 与 Spring Cloud 深度集成 与 Spring Cloud 集成度一般

总的来说,Sentinel 在功能、性能、社区活跃度等方面都优于 Hystrix。Hystrix 已经停止维护,建议在新项目中使用 Sentinel。

八、总结:Sentinel 是 Spring Cloud 的好帮手

Sentinel 就像咱们 Spring Cloud 社区的“守门大爷”,它能有效地保护我们的系统,防止流量过大导致崩溃。虽然学习 Sentinel 需要花费一些时间,但它的功能和性能绝对值得我们投入精力。

希望这篇文章能帮助大家更好地理解和使用 Sentinel。记住,有了 Sentinel,咱们的 Spring Cloud 系统就能更加安全、稳定地运行啦!

最后,祝大家编码愉快,bug 远离!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注