Nacos+Sentinel实现接口限流

Source

1 引入依赖

<!-- 注册中心-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 配置中心 -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- 限流依赖-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
	<version>2021.0.4.0</version>
</dependency>

2 添加配置类

添加配置变更监听,限流策略修改可实时同步到服务

package com.xlt.config;

import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.fastjson.JSON;
import com.geely.idc.imd.anonymize.worker.config.propety.AnonSentinelProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.environment.EnvironmentChangeEvent;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.EventListener;

import javax.annotation.PostConstruct;
import java.util.Set;

@Configuration
public class SentinelConfig {

    private final Logger log = LoggerFactory.getLogger(SentinelConfig.class);

    @Autowired
    private SentinelProperties sentinelProperties;

    @PostConstruct
    public void init() {
        loadFlowRules();
    }

    /**
     * 添加配置变更监听,热更新限流规则
     *
     * @param event
     */
    @EventListener
    public void handleEvent(ApplicationEvent event) {
        if (event instanceof EnvironmentChangeEvent) {
            EnvironmentChangeEvent environmentChangeEvent = (EnvironmentChangeEvent) event;
            Set<String> keys = environmentChangeEvent.getKeys();
            boolean match = keys.stream().anyMatch(e -> e.startsWith(sentinelProperties.getConfigKey()));
            if (match) {
                loadFlowRules();
            }
        }
    }

    private void loadFlowRules() {
        if (sentinelProperties.isEnable()) {
            log.info("Sentinel flow rule changed: {}", JSON.toJSON(sentinelProperties.getRules()));
            FlowRuleManager.loadRules(sentinelProperties.getRules());
        }
    }

}
  

配置类封装限流规则对象

@Data
@Component
@RefreshScope
@ConfigurationProperties(prefix = "sentinel")
public class SentinelProperties {

    private boolean enable = false;

    private List<FlowRule> rules;

    private String configKey = "sentinel.rules";

}

3 标明限流资源

接口添加注解@SentinelResource,与限流规则资源相对应

@PostMapping("/images/anonymize")
@SentinelResource(value = "imageAnonymize")
public ApiResponse<AnonImageVO> anonymize(@RequestBody byte[] file) {
    return anonymizeService.anonymize(file);
}

@PostMapping("/images/anonymize/path")
@SentinelResource(value = "imageAnonymizePath")
public ApiResponse anonymize(@RequestParam(value = "filePath") String filePath) {
    return ApiResponse.success(anonymizeService.anonymize(filePath));
}

4 添加nacos配置

模块配置文件anon-worker.yaml添加限流规则配置

  sentinel:
    enable: true
    rules: 
      - resource: imageAnonymize
        limitApp: default
        grade: 1
        count: 3
        strategy: 0
        controlBehavior: 2
        maxQueueingTimeMs: 2000
        clusterMode: false
      - resource: imageAnonymizePath
        limitApp: default
        grade: 1
        count: 1
        strategy: 0
        controlBehavior: 0
        clusterMode: false

5 配置说明

限流规则配置说明,对于上图的配置Sentinel把它抽象成一个FlowRule类,与其属性一一对应

属性 类型 取值范围 说明
resource String 资源名,与限流接口注解标识保持一致
limitApp String default、other 限流来源,默认为default不区分来源
grade int 0(thread)、1(QPS) 限流类型,有QPS和并发线程数两种类型
count double 限流阈值
strategy int 0(直接)、1(关联)、2(链路)

流控策略

0.直接:当api大达到限流条件时,直接限流
1.关联:当关联的资源到达阈值,就限流自己
2.链路:只记录指定路上的流量,指定资源从入口资源进来的流量,如果达到阈值,就进行限流,api级别的限流

controlBehavior int 0(快速失败)、1(预热启动)、2(排队等待)、3(预热启动排队等待) 流控效果
warmUpPeriodSec int 流控效果为预热启动时的预热时长(秒),默认10s
maxQueueingTimeMs int 流控效果为排队等待时的等待时长 (毫秒),默认500ms
clusterMode boolean 集群模式

注意: 

上述配置只适配单实例服务资源限流,如要引入到集群模式,还需参考Sentinel集群模式配置方式,做相应适配修改。