【系统开发】尚硅谷 - 谷粒商城项目笔记(九):Sentinel高并发方法论

文章目录

  • Sentinel高并发方法论
    • Sentinel是什么?
    • 基本概念及作用
    • 整合SpringBoot
      • 引入Sentinel依赖
      • 下载Sentinel控制台
      • cmd启动Sentinel
      • 配置Sentinel控制台地址信息
      • 在控制台设置流控规则
      • 规则持久化
      • 流量监控
      • 自定义流控返回数据
      • 适配Feign,并加上熔断保护方法
      • 自定义受保护的资源
      • 网关流控


Sentinel高并发方法论

Sentinel是什么?

Sentinel中文文档:https://github.com/alibaba/Sentinel/wiki/介绍

【系统开发】尚硅谷 - 谷粒商城项目笔记(九):Sentinel高并发方法论_第1张图片

随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。

Sentinel 具有以下特征:

  • 丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。
  • 完备的实时监控:Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。
  • 广泛的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Apache Dubbo、gRPC、Quarkus 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。同时 Sentinel 提供 Java/Go/C++ 等多语言的原生实现。
  • 完善的 SPI 扩展机制:Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。

Sentinel的主要特征:

【系统开发】尚硅谷 - 谷粒商城项目笔记(九):Sentinel高并发方法论_第2张图片

Sentinel的开源生态:

Sentinel 分为两个部分:

  • **核心库(Java 客户端)**不依赖任何框架/库,能够运行于所有 Java 运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持。
  • **控制台(Dashboard)**基于 Spring Boot 开发,打包后可以直接运行,不需要额外的 Tomcat 等应用容器。

基本概念及作用

基本概念:

**资源:**是 Sentinel 的关键概念。它可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它应用提供的服务,甚至可以是一段代码。在接下来的文档中,我们都会用资源来描述代码块。

只要通过 Sentinel API 定义的代码,就是资源,能够被 Sentinel 保护起来。大部分情况下,可以使用方法签名,URL,甚至服务名称作为资源名来标示资源。

**规则:**围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则。所有规则可以动态实时调整。

主要作用:

  • 流量控制
  • 熔断降级
  • 系统负载保护

我们说的资源,可以是任何东西,服务,服务里的方法,甚至是一段代码。使用 Sentinel 来进行资源保护,主要分为几个步骤:

  • 定义资源
  • 定义规则
  • 检验规则是否生效

先把可能需要保护的资源定义好,之后再配置规则。也可以理解为,只要有了资源,我们就可以在任何时候灵活地定义各种流量控制规则。在编码的时候,只需要考虑这个代码是否需要保护,如果需要保护,就将之定义为一个资源。

整合SpringBoot

引入Sentinel依赖

<dependency>
    <groupId>com.alibaba.cloudgroupId>
    <artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
dependency>

下载Sentinel控制台

https://github.com/alibaba/Sentinel/tree/master/sentinel-dashboard

注意,版本要与项目中的Sentinel版本一致

【系统开发】尚硅谷 - 谷粒商城项目笔记(九):Sentinel高并发方法论_第3张图片

【系统开发】尚硅谷 - 谷粒商城项目笔记(九):Sentinel高并发方法论_第4张图片

cmd启动Sentinel

image-20220211093746283

访问http://localhost:8333

【系统开发】尚硅谷 - 谷粒商城项目笔记(九):Sentinel高并发方法论_第5张图片

默认用户名和密码都是sentinel

【系统开发】尚硅谷 - 谷粒商城项目笔记(九):Sentinel高并发方法论_第6张图片

配置Sentinel控制台地址信息

appliaction.properties

# Sentinel控制台的端口
spring.cloud.sentinel.transport.dashboard=localhost:8333
# 随便写,只要不被占用就行,一个用来与Sentinel交互的端口
spring.cloud.sentinel.transport.port=8719

启动项目,并在网关处有一个请求通过,就会在Sentinel主页出现网关服务

【系统开发】尚硅谷 - 谷粒商城项目笔记(九):Sentinel高并发方法论_第7张图片

在控制台设置流控规则

(默认流控规则保存在内存中,项目重启就没了)

【系统开发】尚硅谷 - 谷粒商城项目笔记(九):Sentinel高并发方法论_第8张图片

规则持久化

无论是通过硬编码的方式来更新规则,还是通过接入 Sentinel Dashboard 后,在页面上操作更新规则,都无法避免一个问题,那就是服务重启后,规则就丢失了,因为默认情况下规则是保存在内存中的。

我们在 Dashboard 上为客户端配置好了规则,并推送给了客户端。这时由于一些因素客户端出现异常,服务不可用了,当客户端恢复正常再次连接上 Dashboard 后,这时所有的规则都丢失了,我们还需要重新配置一遍规则,这肯定不是我们想要的。

持久化配置分以下3步:

  1. 引入依赖
<dependency>
    <groupId>com.alibaba.cspgroupId>
    <artifactId>sentinel-datasource-nacosartifactId>
dependency>
  1. 添加配置
# 这里datasource后的consumer是数据源名称,可以随便写,推荐使用服务名
spring.cloud.sentinel.datasource.consumer.nacos.server-addr=localhost:8848
spring.cloud.sentinel.datasource.consumer.nacos.dataId=${spring.application.name}-sentinel-rules
spring.cloud.sentinel.datasource.consumer.nacos.groupId=SENTINEL_GROUP
spring.cloud.sentinel.datasource.consumer.nacos.data-type=json
# 规则类型,取值见:org.springframework.cloud.alibaba.sentinel.datasource.RuleType
spring.cloud.sentinel.datasource.consumer.nacos.rule_type=flow
  1. nacos中创建流控规则

【系统开发】尚硅谷 - 谷粒商城项目笔记(九):Sentinel高并发方法论_第9张图片

配置内容如下:

[
    {
        "resource": "/hello",
        "limitApp": "default",
        "grade": 1,
        "count": 2,
        "strategy": 0,
        "controlBehavior": 0,
        "clusterMode": false
    }
]

resource:资源名称

limitApp:限流应用,就是用默认就可以

grade:阈值类型,0表示线程数,1表示qps

count:单机阈值

strategy:流控模式,0-直接,1-关联, 2-链路

controlBehavior:流控效果。0-快速失败,1-warm up 2-排队等待

clusterMode:是否集群

查看sentinel客户端:就有了限流配置了

【系统开发】尚硅谷 - 谷粒商城项目笔记(九):Sentinel高并发方法论_第10张图片

流量监控

利用SpringBoot提供的审计模块,引入spring-boot-starter-actuator依赖

<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-actuatorartifactId>
dependency>

在application.properties中添加配置,让所有服务都暴露给统计模块去统计

management.endpoints.web.exposure.include=*

自定义流控返回数据

@Configuration
public class GulimallSeckillSentinelConfig {
    public GulimallSeckillSentinelConfig() {
        WebCallbackManager.setUrlBlockHandler(new UrlBlockHandler() {
            @Override
            public void blocked(HttpServletRequest request, HttpServletResponse response, BlockException ex) throws IOException {
                R error = R.error(10003, "请求流量过大,请稍后再试");
                response.setCharacterEncoding("UTF-8");
                response.setContentType("application/json");
                response.getWriter().write(JSON.toJSONString(error));
            }
        });
    }
}

【系统开发】尚硅谷 - 谷粒商城项目笔记(九):Sentinel高并发方法论_第11张图片

适配Feign,并加上熔断保护方法

application.properties中加入以下代码,开启sentinel对feign的支持

feign.sentinel.enabled=true

写熔断保护的兜底方法

@Component
public class SeckillFeignServiceFallBack implements SeckillFeignService {
    @Override
    public R getSkuSeckilInfo(Long skuId) {
        return R.error(BizCodeEnum.TO_MANY_REQUEST.getCode(),BizCodeEnum.TO_MANY_REQUEST.getMsg());
    }
}

与远程调用绑定 fallback = SeckillFeignServiceFallBack.class

@FeignClient(value = "gulimall-seckill",fallback = SeckillFeignServiceFallBack.class)
public interface SeckillFeignService {
    @GetMapping(value = "/sku/seckill/{skuId}")
    R getSkuSeckilInfo(@PathVariable("skuId") Long skuId);
}

自定义受保护的资源

在要保护的方法上加上如下注解

@SentinelResource(value = "getCurrentSeckillSkusResource",blockHandler = "blockHandler")

blockHandler是方法被限流之后的回调事件,和被限流的方法写在同一个类中,其返回值和原方法一样,传入参数比原方法多了一个异常值参数

public List<SeckillSkuRedisTo> blockHandler(BlockException e) {
    log.error("getCurrentSeckillSkusResource被限流了,{}",e.getMessage());
    return null;
}

网关流控

引入依赖

<dependency>
    <groupId>com.alibaba.cloudgroupId>
    <artifactId>spring-cloud-alibaba-sentinel-gatewayartifactId>
    <version>版本号和网关一致最好version>
dependency>

自定义流控返回

@Configuration
public class SentinelGatewayConfig {
    public SentinelGatewayConfig() {
        GatewayCallbackManager.setBlockHandler(new BlockRequestHandler() {
            //网关限流了请求,就会调用此回调
            @Override
            public Mono<ServerResponse> handleRequest(ServerWebExchange exchange, Throwable t) {
                R error = R.error(BizCodeEnum.TO_MANY_REQUEST.getCode(), BizCodeEnum.TO_MANY_REQUEST.getMsg());
                String errorJson = JSON.toJSONString(error);
                
                Mono<ServerResponse> body = ServerResponse.ok().body(Mono.just(errorJson), String.class);
                return body;
            }
        });
    }
}

你可能感兴趣的:(系统开发,笔记,sentinel,java,谷粒商城,尚硅谷,高并发)