[Alibaba微服务技术入门]_Sentinel热点参数限流_第14讲

热点限流官方文档:https://github.com/alibaba/Sentinel/wiki/%E7%83%AD%E7%82%B9%E5%8F%82%E6%95%B0%E9%99%90%E6%B5%81

何为热点?热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制

比如:

  • 商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制
  • 用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制

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

Sentinel 利用 LRU 策略统计最近最常访问的热点参数,结合令牌桶算法来进行参数级别的流控。热点参数限流支持集群模式

热点参数限流实战

第一步:在 FlowLimitController 新增 testHotKey 方法,且在方法上加入 @SentinelResource 注解 + 两个参数

package com.liuyangjava.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;

@RestController
public class FlowLimitController {
    @Value("${server.port}")
    private String port;

    private Logger logger = LoggerFactory.getLogger(FlowLimitController.class);

    @GetMapping("/sentinel/service")
    public String getInfo() {
        return "sentinel service is running, server port: " + port;
    }

    @GetMapping("/sentinel/playInfo")
    public String playInfo() {
        logger.info(Thread.currentThread().getName()+"\t"+".../sentinel/playInfo");
        return "sentinel service is playInfo";
    }

    @GetMapping("/sentinel/testRT")
    public String testRT() {
        try {
            // 模拟此接口一秒钟才处理完一个请求,其处理请求时间远大于RT响应时间
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        logger.info(Thread.currentThread().getName()+"\t"+".../sentinel/testRT");
        return "sentinel service RT is Opening";
    }

    @GetMapping("/sentinel/testException")
    public String testException() {
        // 触发异常, 如果异常发生比例超过阈值, 服务熔断降级
        int i = 10 / 0;
        return "sentinel service testException is Opening";
    }

    @GetMapping("/sentinel/testHotKey")
    @SentinelResource(value = "testHotKey")
    public String testHotKey(@RequestParam(value = "p1", required = false) String p1, @RequestParam(value = "p2", required = false) String p2) {
        return "sentinel service resource is Opening";
    }
}

第二步:配置热点参数

 注意:

  • 通过浏览器返回接口 /sentinel/testHotKey,不加入参数的时候,接口是不会出现异常的
  • 但是在接口 /sentinel/testHotKey 上面加入参数p1,进行测试QPS > 1,接口就会出现限流的异常。且后台会抛出 ParamFlowException

 第三步:在 @SentinelResource 注解上加入 blockHandler 属性,通过它来自定义热点参数限流成功后的反馈信息定义

@GetMapping("/sentinel/testHotKey")
@SentinelResource(value = "testHotKey", blockHandler = "handlerTestHotKey")
public String testHotKey(@RequestParam(value = "p1", required = false) String p1, @RequestParam(value = "p2", required = false) String p2) {
    return "sentinel service resource is Opening";
}

public String handlerTestHotKey(String p1, String p2, BlockException exception) {
    return "对不起, 当前流量过高...";
}

参数例外项

  • 我们期望p1参数当它是某个特殊值时,它的限流值和平时不一样

  • 假如,当p1的值等于5时,它的阈值可以达到200

 注意:@SentinelResource只负责热点参数限流的配置,但是如果方法自身发生的异常,@SentinelResource的属性 blockHandler 是不负责处理改异常信息

 

posted @ 2021-11-18 14:21  子墨老师  阅读(110)  评论(0编辑  收藏  举报