sentinel动态服务限流

服务保护的基本概念

服务限流/熔断

服务限流目的是为了更好的保护我们的服务,在高并发的情况下,如果客户端请求的数量达到一定极限(后台可以配置阈值),请求的数量超出了设置的阈值,开启自我的保护,直接调用我们的服务降级的方法,不会执行业务逻辑操作,直接走本地falback的方法,返回一个友好的提示。

服务降级

在高并发的情况下, 防止用户一直等待,采用限流/熔断方法,使用服务降级的方式返回一个友好的提示给客户端,不会执行业务逻辑请求,直接走本地的falback的方法。
提示语:当前排队人数过多,稍后重试~

服务的雪崩效应

默认的情况下,Tomcat或者是Jetty服务器只有一个线程池去处理客户端的请求,
这样的话就是在高并发的情况下,如果客户端所有的请求都堆积到同一个服务接口上,
那么就会产生tomcat服务器所有的线程都在处理该接口,可能会导致其他的接口无法访问。

假设我们的tomcat线程最大的线程数量是为20,这时候客户端如果同时发送100个请求会导致有80个请求暂时无法访问,就会转圈。

服务的隔离的机制

服务的隔离机制分为:信号量和线程池隔离模式
服务的线程池隔离机制:每个服务接口都有自己独立的线程池,互不影响,缺点就是占用cpu资源非常大。
服务的信号量隔离机制:最多只有一定的阈值线程数处理我们的请求,超过该阈值会拒绝请求。

Sentinel 与hytrix区别

前哨以流量为切入点,从流量控制,熔断降级,系统负载保护等多个维度保护服务的稳定性。

前哨具有以下特征:

  1. 丰富的应用场景:前哨兵承接了阿里巴巴近10年的双十一大促流的核心场景,例如秒杀(即突然流量控制在系统容量可以承受的范围),消息削峰填谷,传递流量控制,实时熔断下游不可用应用等。
  2. 完备的实时监控:Sentinel同时提供实时的监控功能。您可以在控制台中看到接收应用的单台机器秒级数据,甚至500台以下规模的整合的汇总运行情况。
    广泛的开源生态:Sentinel提供开箱即用的与其他开源框架/库的集成模块,例如与Spring Cloud,Dubbo,gRPC的整合。您只需要另外的依赖并进行简单的配置即可快速地接入Sentinel。
  3. 完善的SPI扩展点:Sentinel提供简单易用,完善的SPI扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理,适应动态数据源等。
    在这里插入图片描述

SpringBoot项目整合Sentinel

Sentinel 控制台 下载地址

https://github.com/alibaba/Sentinel/releases

启动命令 其中 -Dserver.port=8xxx 用于指定 Sentinel 控制台端口为 8xxx。

java -Dserver.port=8718 -Dcsp.sentinel.dashboard.server=localhost:8718 -Dproject.name=sentinel-dashboard -Dcsp.sentinel.api.port=8719 -jar E:\xxx\sentinel\sentinel-dashboard-1.8.0.jar

默认用户名和密码都是 sentinel

Maven依赖

	<!-- alibaba sentinel 限流熔断-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    </dependency>
    <!-- alibaba sentinel 整合-gateway-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
    </dependency>

客户端接入控制台 Maven依赖

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-transport-simple-http</artifactId>
    <version>x.y.z</version>
</dependency>

配置启动参数

启动时加入 JVM 参数 -Dcsp.sentinel.dashboard.server=consoleIp:port
指定控制台地址和端口。若启动多个应用,则需要通过 -Dcsp.sentinel.api.port=xxxx 指定客户端监控 API
的端口(默认是 8719)。

从 1.6.3 版本开始,控制台支持网关流控规则管理。您需要在接入端添加 -Dcsp.sentinel.app.type=1
启动参数以将您的服务标记为 API Gateway,在接入控制台时您的服务会自动注册为网关类型,然后您即可在控制台配置网关规则和 API
分组。

除了修改 JVM 参数,也可以通过配置文件取得同样的效果。更详细的信息可以参考 启动配置项。

gateway项目整合Sentinel的yml配置

spring:
  cloud:
    # sentinel 配置 注册到控制台地址
    sentinel:
      transport:
        dashboard: 127.0.0.1:8718
      # 默认false 开启true
      eager: true
###配置那些接口需要限流
gateway:
  seckill:
    intercept:
      url: /tst-seckill/spike

SeckillFilter

/**
 * @description: TODO 秒杀服务拦截
 * @author: wang
 * @date: 2020/10/12 12:08
 * @version: v1.0
 */
@Component
public class SeckillFilter implements GlobalFilter, Ordered {

    @Autowired
    private SeckillService seckillService;

    @Value("${gateway.seckill.intercept.url}")
    private List<String> gatewaySeckillInterceptUrl;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpResponse response = exchange.getResponse();
        ServerHttpRequest request = exchange.getRequest();
        HttpHeaders header = response.getHeaders();
        header.add("Content-Type", "application/json; charset=UTF-8");

        RequestPath path = request.getPath();
        // 排除请求 判断地址是否在限流名单里
        boolean resultExist = existSeckillUrl(path.value());
        if (!resultExist) {
            // 直接放行
            return chain.filter(exchange);
        }
        try {
            String userPhone = getParam(request.getURI().getQuery(), "userPhone");
            String seckillId = getParam(request.getURI().getQuery(), "seckillId");
            seckillService.seckill(userPhone, seckillId);
            return chain.filter(exchange);
        } catch (Exception e) {
            JSONObject jsonObject = setResultErrorMsg("当前访问用户过多,请稍后重试");
            DataBuffer buffer = response.bufferFactory().wrap(jsonObject.toJSONString().getBytes());
            return response.writeWith(Mono.just(buffer));
        }

    }

    /**
     * 值越小 排序靠前
     * @return
     */
    @Override
    public int getOrder() {
        return 0;
    }

    /**
     * 返回提示
     * @param msg
     * @return
     */
    private JSONObject setResultErrorMsg(String msg) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("code", "500");
        jsonObject.put("msg", msg);
        return jsonObject;
    }


    /**
     *
     * @param url
     * @param name
     * @return
     */
    public static String getParam(String url, String name) {
        String params = url.substring(url.indexOf("?") + 1, url.length());
        Map<String, String> split = Splitter.on("&").withKeyValueSeparator("=").split(params);
        return split.get(name);
    }

    public boolean existSeckillUrl(String url) {
        return gatewaySeckillInterceptUrl.contains(url);
    }

SeckillService

/**
 * @description: TODO 秒杀服务 限流服务
 * @author: wang
 * @date: 2020/10/12 12:06
 * @version: v1.0
 */
@Component
public class SeckillService {

    /**
     * @SentinelResource-value 资源名称-跟控制台一样
     * @param userPhone
     * @param seckillId
     * @return
     * @throws Exception
     */
    @SentinelResource(value = "seckill", blockHandler = "getSeckillQpsException")
    public String seckill(String userPhone, String seckillId) throws Exception {
        return "success";
    }

    /**
     * 被限流返回的提示
     * @SentinelResource-blockHandler 限流或熔断出现异常执行的方法
     * @param userPhone
     * @param seckillId
     * @param e
     * @return
     * @throws Exception
     */
    public String getSeckillQpsException(String userPhone, String seckillId, BlockException e) throws Exception {
        throw new RuntimeException();
    }
}

Sentinel持久化

默认的情况下Sentinel的规则是存放在内存中,如果Sentinel客户端重启后,Sentinel数据规则可能会丢失。

解决方案:
Sentinel持久化机制支持四种持久化的机制。

  1. 本地文件
  2. 携程阿波罗
  3. Nacos
  4. Zookeeper

Maven依赖

<!--sentinel 整合nacos -->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
</dependency>

在Nacos创建规则yml文件 josn格式

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

resource:资源名,即限流规则的作用对象
limitApp:流控针对的调用来源,若为 default 则不区分调用来源
grade:限流阈值类型(QPS 或并发线程数);0代表根据并发数量来限流,1代表根据QPS来进行流量控制
count:限流阈值
strategy:调用关系限流策略
controlBehavior:流量控制效果(直接拒绝、Warm Up、匀速排队)
clusterMode:是否为集群模式

yaml配置

sentinel:
  transport:
    dashboard: 127.0.0.1:8718
  eager: true
  datasource:
    ds:
      nacos:
        ### nacos连接地址
        server-addr: localhost:8848
        ## nacos连接的分组
        group-id: DEFAULT_GROUP
        ###路由存储规则
        rule-type: flow
        ### 读取配置文件的 data-id
        data-id: xxx-order-sentinel
        ###  读取培训文件类型为json
        data-type: json

–整理自 http://www.mayikt.com/ 仅供自己学习记录

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值